# Sketcher: Change radius of circular edges while dragging a point on the edge
SET(SKETCHER_CHANGE_RADIUS_WHEN_MOVE TRUE)
+SET(MAKE_TRANSLATION YES)
+ ADD_DEFINITIONS( -DMAKE_TRANSLATION )
ADD_SUBDIRECTORY (src/Config)
ADD_SUBDIRECTORY (src/Events)
ADD_SUBDIRECTORY (src/Selector)
.. centered::\r
Construction pop-up menu\r
\r
-The order of features can be changed using *Move to the end* pop-up menu command. It works only for Group features. The selected group will be moved to the end of features list.\r
+The order of features can be changed using *Move to the end* and *Move to the end and split* pop-up menu commands. They work only for Group features. The selected group or several groups will be moved to the end of features list. The *Move to the end and split* also splits the resulting group in several groups: one group per one selection.\r
\r
Folders can be used to arrange long Tree View for features.\r
\r
\r
**Input fields**:\r
\r
+- **Selection color** defines a color for selected objects;\r
- **Result color** selects default shading color for objects from **Results** branch;\r
- **Group color** selects default color for objects from **Groups** branch;\r
- **Construction color** selects default color for objects from **Constructions** branch;\r
\r
.. _sketch_preferences:\r
\r
+Shortcuts tab\r
+^^^^^^^^^^^^^\r
+\r
+Shortcuts tab defines shortcut keys for different operations.\r
+\r
+.. image:: images/shortcuts_preferences.png\r
+ :align: center\r
+\r
+.. centered::\r
+ Preferences - Shortcuts tab\r
+ \r
+- **Add parameter in parameters manager dialog** defines shortcut keys for adding parameter in parameters manager dialog box.\r
+ \r
+Windows tab\r
+^^^^^^^^^^^\r
+\r
+Windows tab contains definitions for the module windows management.\r
+\r
+.. image:: images/windows_preferences.png\r
+ :align: center\r
+\r
+.. centered::\r
+ Preferences - Windows tab\r
+\r
+- **Use HideFaces panel in operation** if the checkbox is checked then HideFaces panel will be launched automatically on launching an operation where using of this panel is considered.\r
+\r
Sketch tab\r
^^^^^^^^^^\r
\r
- **Size** defines size of coordinate planes;\r
- **Thickness** defines thickness of coordinate plane borders; \r
- **Rotate to plane when selected** check-box turns on/off automatic switch the viewer to the top view for the selected sketch plane. \r
+- **Angular tolerance** defines defines an angular tolerance for automatic creation of horizontal and vertical constraints;\r
\r
\r
.. _viewer_preferences:\r
##
#------ SHAPER ------
-export PATH=${SHAPER_ROOT_DIR}/bin/salome:${PATH}
-export PYTHONPATH=${SHAPER_ROOT_DIR}/bin/salome:${SHAPER_ROOT_DIR}/lib/python3.6/site-packages/salome:${PYTHONPATH}
+export SHAPER_BIN_DIR=${SHAPER_ROOT_DIR}/bin/salome
+export SHAPER_PYTHON_SCRIPTS_DIR=${SHAPER_ROOT_DIR}/lib/python3.6/site-packages/salome
+export PATH=${SHAPER_BIN_DIR}:${PATH}
+export PYTHONPATH=${SHAPER_BIN_DIR}:${SHAPER_PYTHON_SCRIPTS_DIR}:${PYTHONPATH}
export LD_LIBRARY_PATH=${SHAPER_ROOT_DIR}/lib/salome:${LD_LIBRARY_PATH}
//==================================================================================================
BuildAPI_Edge::BuildAPI_Edge(const std::shared_ptr<ModelAPI_Feature>& theFeature,
- const std::list<ModelHighAPI_Selection>& theBaseObjects)
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections)
: ModelHighAPI_Interface(theFeature)
{
if(initialize()) {
fillAttribute(BuildPlugin_Edge::CREATION_BY_SEGMENTS(), mycreationMethod);
+ fillAttribute(theComputeIntersections, mycomputeIntersections);
setBase(theBaseObjects);
}
}
theDumper << aBase->selection(BuildPlugin_Edge::FIRST_POINT()) << ", "
<< aBase->selection(BuildPlugin_Edge::SECOND_POINT());
}
- else
+ else {
theDumper << aBase->selectionList(BuildPlugin_Edge::BASE_OBJECTS_ID());
+
+ AttributeBooleanPtr isIntersect = aBase->boolean(BuildPlugin_Edge::INTERSECT_ID());
+ if (isIntersect->isInitialized())
+ theDumper << ", " << isIntersect;
+ }
theDumper << ")" << std::endl;
}
//==================================================================================================
EdgePtr addEdge(const std::shared_ptr<ModelAPI_Document>& thePart,
- const std::list<ModelHighAPI_Selection>& theBaseObjects)
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections)
{
std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Edge::ID());
- return EdgePtr(new BuildAPI_Edge(aFeature, theBaseObjects));
+ return EdgePtr(new BuildAPI_Edge(aFeature, theBaseObjects, theComputeIntersections));
}
EdgePtr addEdge(const std::shared_ptr<ModelAPI_Document>& thePart,
/// Constructor with values.
BUILDAPI_EXPORT
explicit BuildAPI_Edge(const std::shared_ptr<ModelAPI_Feature>& theFeature,
- const std::list<ModelHighAPI_Selection>& theBaseObjects);
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections = false);
/// Constructor by points.
BUILDAPI_EXPORT
BUILDAPI_EXPORT
virtual ~BuildAPI_Edge();
- INTERFACE_4(BuildPlugin_Edge::ID(),
+ INTERFACE_5(BuildPlugin_Edge::ID(),
baseObjects, BuildPlugin_Edge::BASE_OBJECTS_ID(),
ModelAPI_AttributeSelectionList, /** Base objects */,
creationMethod, BuildPlugin_Edge::CREATION_METHOD(),
firstPoint, BuildPlugin_Edge::FIRST_POINT(),
ModelAPI_AttributeSelection, /** First point */,
secondPoint, BuildPlugin_Edge::SECOND_POINT(),
- ModelAPI_AttributeSelection, /** Second point */)
+ ModelAPI_AttributeSelection, /** Second point */,
+ computeIntersections, BuildPlugin_Edge::INTERSECT_ID(),
+ ModelAPI_AttributeBoolean, /** Intersect edges */)
/// Modify base attribute of the feature.
BUILDAPI_EXPORT
/// \brief Create Edge feature.
BUILDAPI_EXPORT
EdgePtr addEdge(const std::shared_ptr<ModelAPI_Document>& thePart,
- const std::list<ModelHighAPI_Selection>& theBaseObjects);
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersection = false);
/// \ingroup CPPHighAPI
/// \brief Create Edge feature.
BUILDAPI_EXPORT
: ModelHighAPI_Interface(theFeature)
{
if(initialize()) {
+ fillAttribute(false, mydoIntersect);
+ setBase(theBaseObjects);
+ }
+}
+
+//==================================================================================================
+BuildAPI_Vertex::BuildAPI_Vertex(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theDoIntersect)
+: ModelHighAPI_Interface(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theDoIntersect, mydoIntersect);
setBase(theBaseObjects);
}
}
return VertexPtr(new BuildAPI_Vertex(aFeature, theBaseObjects));
}
+//==================================================================================================
+VertexPtr addVertex(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theDoIntersect)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Vertex::ID());
+ return VertexPtr(new BuildAPI_Vertex(aFeature, theBaseObjects, theDoIntersect));
+}
+
//==================================================================================================
void BuildAPI_Vertex::dump(ModelHighAPI_Dumper& theDumper) const
{
std::string aPartName = theDumper.name(aBase->document());
theDumper << aBase << " = model.addVertex(" << aPartName << ", "
- << aBase->selectionList(BuildPlugin_Vertex::BASE_OBJECTS_ID()) << ")" << std::endl;
+ << aBase->selectionList(BuildPlugin_Vertex::BASE_OBJECTS_ID()) << ", "
+ << aBase->boolean(BuildPlugin_Vertex::INTERSECT_ID()) << ")" << std::endl;
}
explicit BuildAPI_Vertex(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const std::list<ModelHighAPI_Selection>& theBaseObjects);
+ /// Constructor with values.
+ BUILDAPI_EXPORT
+ explicit BuildAPI_Vertex(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theDoIntersect);
+
/// Destructor.
BUILDAPI_EXPORT
virtual ~BuildAPI_Vertex();
- INTERFACE_1(BuildPlugin_Vertex::ID(),
+ INTERFACE_2(BuildPlugin_Vertex::ID(),
baseObjects, BuildPlugin_Vertex::BASE_OBJECTS_ID(),
- ModelAPI_AttributeSelectionList, /** Base objects */)
+ ModelAPI_AttributeSelectionList, /** Base objects */,
+ doIntersect, BuildPlugin_Vertex::INTERSECT_ID(),
+ ModelAPI_AttributeBoolean, /** Compute intersections */)
/// Modify base attribute of the feature.
BUILDAPI_EXPORT
VertexPtr addVertex(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects);
+/// \ingroup CPPHighAPI
+/// \brief Create Vertex feature.
+BUILDAPI_EXPORT
+VertexPtr addVertex(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theDoIntersect);
+
#endif // BuildAPI_Vertex_H_
//==================================================================================================
BuildAPI_Wire::BuildAPI_Wire(const std::shared_ptr<ModelAPI_Feature>& theFeature,
- const std::list<ModelHighAPI_Selection>& theBaseObjects)
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections)
: ModelHighAPI_Interface(theFeature)
{
if(initialize()) {
+ fillAttribute(theComputeIntersections, mycomputeIntersections);
setBase(theBaseObjects);
}
}
std::string aPartName = theDumper.name(aBase->document());
theDumper << aBase << " = model.addWire(" << aPartName << ", "
- << aBase->selectionList(BuildPlugin_Wire::BASE_OBJECTS_ID()) << ")" << std::endl;
+ << aBase->selectionList(BuildPlugin_Wire::BASE_OBJECTS_ID());
+
+ AttributeBooleanPtr isIntersect = aBase->boolean(BuildPlugin_Wire::INTERSECT_ID());
+ if (isIntersect->isInitialized())
+ theDumper << ", " << isIntersect;
+
+ theDumper << ")" << std::endl;
}
//==================================================================================================
//==================================================================================================
WirePtr addWire(const std::shared_ptr<ModelAPI_Document>& thePart,
- const std::list<ModelHighAPI_Selection>& theBaseObjects)
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections)
{
std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(BuildAPI_Wire::ID());
- return WirePtr(new BuildAPI_Wire(aFeature, theBaseObjects));
+ return WirePtr(new BuildAPI_Wire(aFeature, theBaseObjects, theComputeIntersections));
}
/// Constructor with values.
BUILDAPI_EXPORT
explicit BuildAPI_Wire(const std::shared_ptr<ModelAPI_Feature>& theFeature,
- const std::list<ModelHighAPI_Selection>& theBaseObjects);
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections = false);
/// Destructor.
BUILDAPI_EXPORT
virtual ~BuildAPI_Wire();
- INTERFACE_1(BuildPlugin_Wire::ID(),
+ INTERFACE_2(BuildPlugin_Wire::ID(),
baseObjects, BuildPlugin_Wire::BASE_OBJECTS_ID(),
- ModelAPI_AttributeSelectionList, /** Base objects */)
+ ModelAPI_AttributeSelectionList, /** Base objects */,
+ computeIntersections, BuildPlugin_Wire::INTERSECT_ID(),
+ ModelAPI_AttributeBoolean, /** Intersect edges */)
/// Modify base attribute of the feature.
BUILDAPI_EXPORT
/// \brief Create Wire feature.
BUILDAPI_EXPORT
WirePtr addWire(const std::shared_ptr<ModelAPI_Document>& thePart,
- const std::list<ModelHighAPI_Selection>& theBaseObjects);
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const bool theComputeIntersections = false);
#endif // BuildAPI_Wire_H_
#include "BuildPlugin_Edge.h"
+#include <ModelAPI_AttributeBoolean.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
#include <GeomAlgoAPI_Copy.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_Partition.h>
#include <GeomAlgoAPI_Tools.h>
#include <GeomAPI_Edge.h>
data()->addAttribute(FIRST_POINT(), ModelAPI_AttributeSelection::typeId());
data()->addAttribute(SECOND_POINT(), ModelAPI_AttributeSelection::typeId());
+
+ data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID());
}
//=================================================================================================
// Collect base shapes.
ListOfShape aListOfShapes;
std::string aError;
- int aResultIndex = 0;
for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
GeomShapePtr aShape;
setError("Error: Empty shape selected.");
return;
}
+ aListOfShapes.push_back(aShape);
+ }
- if(aShape->shapeType() != GeomAPI_Shape::EDGE) {
- setError("Error: Selected shape has wrong type. Only edges acceptable.");
- return;
- }
+ AttributeBooleanPtr isIntersect = boolean(INTERSECT_ID());
- // Copy shape.
- GeomMakeShapePtr aCopyAlgo(new GeomAlgoAPI_Copy(aShape));
+ GeomShapePtr aResult;
+ std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo;
+ if (isIntersect->isInitialized() && isIntersect->value()) {
+ aPartitionAlgo.reset(new GeomAlgoAPI_Partition(aListOfShapes, ListOfShape()));
std::string anError;
- if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) {
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
setError(anError);
return;
}
- // Store result.
- ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+ aResult = aPartitionAlgo->shape();
+ }
+ else
+ aResult = GeomAlgoAPI_CompoundBuilder::compound(aListOfShapes);
+
+ int aResultIndex = 0;
+
+ // Explode on edges
+ std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aProcessed;
+ for (GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdge = anExp.current();
+ if (aProcessed.find(anEdge) != aProcessed.end())
+ continue; // vertex is already processed
+ aProcessed.insert(anEdge);
- ListOfShape aBaseShapes;
- aBaseShapes.push_back(aShape);
- aResultBody->storeModified(aBaseShapes, aCopyAlgo->shape(), aCopyAlgo);
- aResultBody->loadModifiedShapes(aCopyAlgo, aShape, GeomAPI_Shape::VERTEX);
+ std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(anEdge));
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
+ if (aPartitionAlgo)
+ aMakeShapeList->appendAlgo(aPartitionAlgo);
+ aMakeShapeList->appendAlgo(aCopyAlgo);
+
+ // Store result.
+ ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+ aResultBody->storeModified(aListOfShapes, aCopyAlgo->shape(), aMakeShapeList);
+ aResultBody->loadModifiedShapes(aMakeShapeList, anEdge, GeomAPI_Shape::VERTEX);
setResult(aResultBody, aResultIndex);
++aResultIndex;
}
return MY_SECOND_POINT_ID;
}
+ /// Attribute name of "Compute intersections" checkbox.
+ inline static const std::string& INTERSECT_ID()
+ {
+ static const std::string MY_INTERSECT_ID("intersect");
+ return MY_INTERSECT_ID;
+ }
+
/// Request for initialization of data model of the feature: adding all attributes.
BUILDPLUGIN_EXPORT virtual void initAttributes();
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultConstruction.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_PlanarEdges.h>
if(!aShape.get()) {
aShape = aContext;
}
- // keep selected faces "as is"
if (aShape->shapeType() == GeomAPI_Shape::FACE) {
+ // keep selected faces "as is"
anOriginalFaces.push_back(aShape);
continue;
}
+ else if (!aSelection->value() && aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+ // collect faces from the sketch
+ ResultConstructionPtr aSketch =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelection->context());
+ if (aSketch && aSketch->facesNum() > 0) {
+ for (int i = 0; i < aSketch->facesNum(); ++i)
+ anOriginalFaces.push_back(aSketch->face(i));
+ continue;
+ }
+ }
for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
GeomShapePtr anEdge = anExp.current();
new BuildPlugin_ValidatorSubShapesSelection());
aFactory->registerValidator("BuildPlugin_ValidatorFillingSelection",
new BuildPlugin_ValidatorFillingSelection());
+ aFactory->registerValidator("BuildPlugin_ValidatorBaseForVertex",
+ new BuildPlugin_ValidatorBaseForVertex());
// Register this plugin.
ModelAPI_Session::get()->registerPlugin(this);
ListOfShape aShapes, aContexts;
getOriginalShapesAndContexts(BASE_OBJECTS_ID(), aShapes, aContexts);
+ // Collect sketch faces.
+ for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+ GeomShapePtr aShape = aSelection->value();
+ ResultConstructionPtr aContext =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelection->context());
+ if (!aShape && aContext) {
+ for (int i = 0; i < aContext->facesNum(); ++i)
+ aShapes.push_back(aContext->face(i));
+ }
+ }
+
// Sew faces.
GeomMakeShapePtr aSewingAlgo(new GeomAlgoAPI_Sewing(aShapes));
#include <GeomValidators_FeatureKind.h>
#include <GeomValidators_ShapeType.h>
+#include <SketchPlugin_Sketch.h>
+
#include <Events_InfoMessage.h>
//=================================================================================================
theError = "Infinite objects not acceptable.";
return false;
}
-
- std::shared_ptr<GeomAPI_PlanarEdges> anEdges =
- std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aContextShape);
- if(anEdges.get()) {
- if(aShape->isEqual(aContextShape)) {
- // It is whole sketch.
- return false;
- }
-
- continue;
- }
}
}
Events_InfoMessage& theError) const
{
// Get attribute.
- if(theArguments.size() != 1) {
- std::string aMsg = "Error: BuildPlugin_ValidatorBaseForWire should be used only "
- "with 1 parameter (ID of base objects list).";
- Events_InfoMessage("BuildPlugin_Validators", aMsg).send();
- return false;
- }
AttributeSelectionListPtr aSelectionList = theFeature->selectionList(theArguments.front());
if(!aSelectionList.get()) {
theError = "Empty attribute \"%1\".";
return false;
}
+ GeomAPI_Shape::ShapeType aShapeType = GeomAPI_Shape::shapeTypeByStr(theArguments.back());
// Collect base shapes.
ListOfShape aListOfShapes;
for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
GeomShapePtr aShape = aSelection->value();
- if(!aShape.get()) {
- if (aSelection->context().get())
- aShape = aSelection->context()->shape();
- }
- if (aShape.get())
+ ResultPtr aContext = aSelection->context();
+ if (!aShape.get() && aContext.get())
+ aShape = aContext->shape();
+
+ bool isProper = aShape.get() &&
+ (aShape->shapeType() == GeomAPI_Shape::EDGE || aShape->shapeType() == aShapeType);
+
+ if (isProper)
aListOfShapes.push_back(aShape);
+ else {
+ // is it a sketch?
+ FeaturePtr aFeature = aSelection->contextFeature();
+ if (!aFeature.get()) {
+ GeomShapePtr aValue = aSelection->value();
+ // whole sketch is allowed only
+ if (aContext.get() && !aValue.get()) {
+ aFeature = ModelAPI_Feature::feature(aContext);
+ }
+ }
+
+ if (!aFeature.get()) {
+ theError = "Error: Incorrect selection.";
+ return false;
+ }
+
+ if (aFeature->getKind() != SketchPlugin_Sketch::ID()) {
+ theError = "Error: %1 shape is not allowed for selection.";
+ theError.arg(aFeature->getKind());
+ return false;
+ }
+ }
}
- // Create wire.
- GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
- if(!aWire.get()) {
- theError = "Result wire empty. Probably it has disconnected edges or non-manifold.";
- return false;
+ if (aShapeType == GeomAPI_Shape::WIRE) {
+ // Create wire.
+ GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(aListOfShapes);
+ if (!aWire.get() && !aListOfShapes.empty()) {
+ theError = "Result wire empty. Probably it has disconnected edges or non-manifold.";
+ return false;
+ }
}
return true;
}
aShape = aSelection->context()->shape();
}
- if (aShape->shapeType() == GeomAPI_Shape::FACE) {
+ ResultConstructionPtr aSketchRes =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelection->context());
+
+ if (aShape->shapeType() == GeomAPI_Shape::FACE ||
+ (!aSelection->value() && aSketchRes && aSketchRes->facesNum() > 0)) {
// skip faces exploding
hasFaces = true;
continue;
return false;
}
- FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+ //FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
// Check selected shapes.
for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
return true;
}
+
+
+//=================================================================================================
+bool BuildPlugin_ValidatorBaseForVertex::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& /*theArguments*/,
+ Events_InfoMessage& theError) const
+{
+ if (!theAttribute.get()) {
+ theError = "Error: empty selection.";
+ return false;
+ }
+
+ AttributeSelectionListPtr aSelectionList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if (!aSelectionList.get()) {
+ theError = "Could not get selection list.";
+ return false;
+ }
+
+ for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr aSelectionAttr = aSelectionList->value(anIndex);
+ if (!aSelectionAttr.get()) {
+ theError = "Empty attribute in list.";
+ return false;
+ }
+
+ // Vertex?
+ bool isVertex = false;
+ GeomShapePtr aShape = aSelectionAttr->value();
+ ResultPtr aContext = aSelectionAttr->context();
+ if (!aShape.get() && aContext.get())
+ aShape = aContext->shape();
+ if (aShape.get())
+ isVertex = (aShape->shapeType() == GeomAPI_Shape::VERTEX);
+
+ if (!isVertex) {
+ // Sketch?
+ FeaturePtr aFeature = aSelectionAttr->contextFeature();
+ if (!aFeature.get()) {
+ GeomShapePtr aValue = aSelectionAttr->value();
+ // whole sketch is allowed only
+ if (aContext.get() && !aValue.get()) {
+ aFeature = ModelAPI_Feature::feature(aContext);
+ }
+ }
+
+ if (!aFeature.get()) {
+ theError = "Error: Incorrect selection.";
+ return false;
+ }
+
+ if (aFeature->getKind() != SketchPlugin_Sketch::ID()) {
+ theError = "Error: %1 shape is not allowed for selection.";
+ theError.arg(aFeature->getKind());
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
Events_InfoMessage& theError) const;
};
+/// \class BuildPlugin_ValidatorBaseForVertex
+/// \ingroup Validators
+/// \brief A validator for selection of Vertex feature.
+class BuildPlugin_ValidatorBaseForVertex: public ModelAPI_AttributeValidator
+{
+public:
+ //! Returns true if attribute is ok.
+ //! \param[in] theAttribute the checked attribute.
+ //! \param[in] theArguments arguments of the attribute.
+ //! \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
#endif
#include "BuildPlugin_Vertex.h"
#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Session.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
#include <GeomAlgoAPI_Copy.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
#include <GeomAlgoAPI_Tools.h>
+#include <GeomAlgoAPI_Partition.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <GeomAPI_ShapeExplorer.h>
//=================================================================================================
BuildPlugin_Vertex::BuildPlugin_Vertex()
void BuildPlugin_Vertex::initAttributes()
{
data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+
+ data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID());
}
-//=================================================================================================
-void BuildPlugin_Vertex::execute()
+void BuildPlugin_Vertex::buildVertices(const ListOfShape& theShapes, bool isIntersect)
{
- // Get base objects list.
- AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
- if(!aSelectionList.get()) {
- setError("Error: Could not get selection list.");
- return;
- }
- if(aSelectionList->size() == 0) {
- setError("Error: Empty selection list.");
- return;
- }
+ GeomShapePtr aResult;
+ std::shared_ptr<GeomAlgoAPI_Partition> aPartitionAlgo;
+ if (isIntersect) {
+ aPartitionAlgo.reset(new GeomAlgoAPI_Partition(theShapes, ListOfShape()));
- // Collect base shapes.
- ListOfShape aListOfShapes;
- int aResultIndex = 0;
- for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
- AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
- GeomShapePtr aShape = aSelection->value();
- if(!aShape.get()) {
- ResultPtr aContext = aSelection->context();
- if(!aContext.get()) {
- setError("Error: Attribute has empty context.");
- return;
- }
-
- aShape = aContext->shape();
- }
- if(!aShape.get()) {
- setError("Error: Empty shape selected.");
+ std::string anError;
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPartitionAlgo, getKind(), anError)) {
+ setError(anError);
return;
}
- if(aShape->shapeType() != GeomAPI_Shape::VERTEX) {
- setError("Error: Selected shape has wrong type. Only vertices acceptable.");
- return;
- }
+ aResult = aPartitionAlgo->shape();
+ }
+ else
+ aResult = GeomAlgoAPI_CompoundBuilder::compound(theShapes);
- // Copy shape.
- std::shared_ptr<GeomAlgoAPI_Copy> aCopyAlgo(new GeomAlgoAPI_Copy(aShape));
+ int aResultIndex = 0;
- std::string anError;
- if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aCopyAlgo, getKind(), anError)) {
- setError(anError);
- return;
- }
+ // Explode on vertices
+ std::set<GeomVertexPtr, GeomAPI_Vertex::GeometricComparator> aProcessed;
+ for (GeomAPI_ShapeExplorer anExp(aResult, GeomAPI_Shape::VERTEX); anExp.more(); anExp.next()) {
+ GeomVertexPtr aVertex(new GeomAPI_Vertex(anExp.current()));
+ if (aProcessed.find(aVertex) != aProcessed.end())
+ continue; // vertex is already processed
+ aProcessed.insert(aVertex);
+
+ std::shared_ptr<GeomAlgoAPI_Copy> aCopy(new GeomAlgoAPI_Copy(aVertex));
+ aVertex.reset(new GeomAPI_Vertex(aCopy->shape()));
+
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
+ if (aPartitionAlgo)
+ aMakeShapeList->appendAlgo(aPartitionAlgo);
+ aMakeShapeList->appendAlgo(aCopy);
// Store result.
ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
- aResultBody->storeModified(aShape, aCopyAlgo->shape());
+ aResultBody->storeModified(theShapes, aVertex, aMakeShapeList);
setResult(aResultBody, aResultIndex);
++aResultIndex;
}
removeResults(aResultIndex);
}
+
+static void collectEdgesAndVertices(AttributeSelectionPtr theSelection, ListOfShape& thePrimitives)
+{
+ FeaturePtr aFeature = theSelection->contextFeature();
+ ResultPtr aContext = theSelection->context();
+ GeomShapePtr aShape = theSelection->value();
+ if (aShape)
+ thePrimitives.push_back(aShape);
+ else {
+ if (aContext && !aFeature)
+ aFeature = ModelAPI_Feature::feature(aContext);
+ if (!aFeature)
+ return;
+
+ // process results of the feature
+ const std::list<ResultPtr>& aResults = aFeature->results();
+ std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+ for (; anIt != aResults.end(); ++anIt)
+ thePrimitives.push_back((*anIt)->shape());
+
+ CompositeFeaturePtr aComposite =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
+ if (!aComposite)
+ return;
+
+ // add construction points (centers of circles, etc.)
+ for (int i = 0, nbSubs = aComposite->numberOfSubs(); i < nbSubs; ++i) {
+ FeaturePtr aSubFeature = aComposite->subFeature(i);
+ const std::list<ResultPtr>& aSubResults = aSubFeature->results();
+ // find all points
+ for (anIt = aSubResults.begin(); anIt != aSubResults.cend(); ++anIt) {
+ GeomShapePtr aSubResShape = (*anIt)->shape();
+ if (aSubResShape->isVertex())
+ thePrimitives.push_back(aSubResShape);
+ }
+ }
+ }
+}
+
+void BuildPlugin_Vertex::execute()
+{
+ // Get base objects list.
+ AttributeSelectionListPtr aSelectionList = selectionList(BASE_OBJECTS_ID());
+ if (!aSelectionList.get()) {
+ setError("Error: Could not get selection list.");
+ return;
+ }
+ if (aSelectionList->size() == 0) {
+ setError("Error: Empty selection list.");
+ return;
+ }
+
+ // Get "Compute intersections" flag value
+ bool isIntersect = false;
+ if (boolean(INTERSECT_ID()).get() && boolean(INTERSECT_ID())->isInitialized()) {
+ isIntersect = boolean(INTERSECT_ID())->value();
+ }
+
+ // Iterate arguments and collect shapes
+ ListOfShape aShapes;
+ for (int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
+ collectEdgesAndVertices(aSelection, aShapes);
+ }
+
+ buildVertices(aShapes, isIntersect);
+}
#include "BuildPlugin.h"
#include <ModelAPI_Feature.h>
+#include <GeomAPI_Shape.h>
/// \class BuildPlugin_Vertex
/// \ingroup Plugins
return MY_BASE_OBJECTS_ID;
}
+ /// Attribute name of "Compute intersections" checkbox.
+ inline static const std::string& INTERSECT_ID()
+ {
+ static const std::string MY_INTERSECT_ID("intersect");
+ return MY_INTERSECT_ID;
+ }
+
/// \return the kind of a feature.
BUILDPLUGIN_EXPORT virtual const std::string& getKind()
{
/// Creates a new part document if needed.
BUILDPLUGIN_EXPORT virtual void execute();
+
+protected:
+ void buildVertices(const ListOfShape& theShapes, bool isIntersect);
};
#endif
#include "BuildPlugin_Wire.h"
+#include <ModelAPI_AttributeBoolean.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
#include <Events_InfoMessage.h>
#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_Vertex.h>
-#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomAlgoAPI_MakeShapeList.h>
+#include <GeomAlgoAPI_PaveFiller.h>
+#include <GeomAlgoAPI_SketchBuilder.h>
+#include <GeomAlgoAPI_Tools.h>
#include <GeomAlgoAPI_WireBuilder.h>
+#include <SketchPlugin_Sketch.h>
+
#include <algorithm>
+static bool buildSketchWires(FeaturePtr theSketchFeature, GeomShapePtr theSketchShape,
+ bool isIntersect,
+ ListOfShape& theWires, GeomMakeShapePtr& theAlgo,
+ std::string& theError);
+
+static bool buildWire(const ListOfShape& theEdges, GeomShapePtr& theWire, std::string& theError);
+
//=================================================================================================
BuildPlugin_Wire::BuildPlugin_Wire()
{
void BuildPlugin_Wire::initAttributes()
{
data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
+
+ data()->addAttribute(INTERSECT_ID(), ModelAPI_AttributeBoolean::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), INTERSECT_ID());
}
//=================================================================================================
return;
}
+ AttributeBooleanPtr anIntersectAttr = boolean(INTERSECT_ID());
+ bool isIntersect = anIntersectAttr->isInitialized() && anIntersectAttr->value();
+
// Collect base shapes.
ListOfShape anEdges;
+ std::list< std::pair<FeaturePtr, GeomShapePtr> > aSketches;
for(int anIndex = 0; anIndex < aSelectionList->size(); ++anIndex) {
AttributeSelectionPtr aSelection = aSelectionList->value(anIndex);
GeomShapePtr aShape = aSelection->value();
if(!aShape.get()) {
aShape = aSelection->context()->shape();
+
+ std::shared_ptr<GeomAPI_PlanarEdges> aSketchShape =
+ std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aShape);
+ if (aSketchShape) {
+ FeaturePtr aSketchFeature = ModelAPI_Feature::feature(aSelection->context());
+ aSketches.push_back(std::pair<FeaturePtr, GeomShapePtr>(aSketchFeature, aSketchShape));
+ continue;
+ }
}
for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
GeomShapePtr anEdge = anExp.current();
}
}
- // Create wire.
- GeomShapePtr aWire = GeomAlgoAPI_WireBuilder::wire(anEdges);
- if(!aWire.get()) {
- setError("Error: Result wire is empty. Probably it has disconnected edges or non-manifold.");
- return;
- }
+ int aResultIndex = 0;
+ std::string anError;
- // Store result.
- ResultBodyPtr aResultBody = document()->createBody(data());
- aResultBody->store(aWire);
- for(GeomAPI_ShapeExplorer anExp(aWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
- GeomShapePtr anEdgeInResult = anExp.current();
- for(ListOfShape::const_iterator anIt = anEdges.cbegin(); anIt != anEdges.cend(); ++anIt) {
- std::shared_ptr<GeomAPI_Edge> anEdgeInList(new GeomAPI_Edge(*anIt));
- if(anEdgeInList->isEqual(anEdgeInResult)) {
- aResultBody->modified(anEdgeInList, anEdgeInResult);
- break;
+ if (!anEdges.empty()) {
+ // Create wire from the list of edges.
+ GeomShapePtr aWire;
+ if (!buildWire(anEdges, aWire, anError)) {
+ setError(anError);
+ return;
+ }
+
+ // Store result.
+ ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+ aResultBody->store(aWire);
+ for (GeomAPI_ShapeExplorer anExp(aWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ GeomShapePtr anEdgeInResult = anExp.current();
+ for (ListOfShape::const_iterator anIt = anEdges.cbegin(); anIt != anEdges.cend(); ++anIt) {
+ std::shared_ptr<GeomAPI_Edge> anEdgeInList(new GeomAPI_Edge(*anIt));
+ if (anEdgeInList->isEqual(anEdgeInResult)) {
+ aResultBody->modified(anEdgeInList, anEdgeInResult);
+ break;
+ }
}
}
+ setResult(aResultBody, aResultIndex);
+ ++aResultIndex;
}
- setResult(aResultBody);
+
+ // create wires from sketches
+ for (std::list<std::pair<FeaturePtr, GeomShapePtr> >::iterator anIt = aSketches.begin();
+ anIt != aSketches.end(); ++anIt) {
+ ListOfShape aWires;
+ GeomMakeShapePtr aMakeShapeList;
+ if (!buildSketchWires(anIt->first, anIt->second, isIntersect,
+ aWires, aMakeShapeList, anError)) {
+ setError(anError);
+ return;
+ }
+
+ for (ListOfShape::iterator aWIt = aWires.begin(); aWIt != aWires.end(); ++aWIt) {
+ ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
+ ListOfShape aSketches;
+ aSketches.push_back(anIt->second);
+ aResultBody->storeModified(aSketches, *aWIt, aMakeShapeList);
+ aResultBody->loadModifiedShapes(aMakeShapeList, anIt->second, GeomAPI_Shape::EDGE);
+ setResult(aResultBody, aResultIndex);
+ ++aResultIndex;
+ }
+ }
+
+ removeResults(aResultIndex);
}
//=================================================================================================
return true;
}
+
+
+
+// ===================== Auxiliary functions ==============================================
+
+bool buildWire(const ListOfShape& theEdges, GeomShapePtr& theWire, std::string& theError)
+{
+ theWire = GeomAlgoAPI_WireBuilder::wire(theEdges);
+ if (!theWire.get()) {
+ theError = "Error: Result wire is empty. Probably it has disconnected edges or non-manifold.";
+ return false;
+ }
+ return true;
+}
+
+bool buildSketchWires(FeaturePtr theSketchFeature, GeomShapePtr theSketchShape, bool isIntersect,
+ ListOfShape& theWires, GeomMakeShapePtr& theAlgo, std::string& theError)
+{
+ ListOfShape aSketchEdges =
+ std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theSketchShape)->getEdges();
+
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList> anAlgoList(new GeomAlgoAPI_MakeShapeList);
+ if (isIntersect) {
+ std::set<GeomShapePtr, GeomAPI_Shape::Comparator> aProcessedEdges;
+ // perform sketch builder first
+ AttributePointPtr anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+ theSketchFeature->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+ AttributeDirPtr aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketchFeature->attribute(SketchPlugin_Sketch::NORM_ID()));
+ AttributeDirPtr aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketchFeature->attribute(SketchPlugin_Sketch::DIRX_ID()));
+ std::shared_ptr<GeomAlgoAPI_SketchBuilder> aSketchBuilder(new GeomAlgoAPI_SketchBuilder(
+ anOrigin->pnt(), aDirX->dir(), aNormal->dir(), theSketchShape));
+
+ anAlgoList->appendAlgo(aSketchBuilder);
+
+ // collect wires from faces
+ const ListOfShape& aFaces = aSketchBuilder->faces();
+ for (ListOfShape::const_iterator anIt = aFaces.begin(); anIt != aFaces.end(); ++anIt) {
+ for (GeomAPI_ShapeExplorer aWExp(*anIt, GeomAPI_Shape::WIRE); aWExp.more(); aWExp.next()) {
+ GeomAPI_ShapeExplorer aEExp(aWExp.current(), GeomAPI_Shape::EDGE);
+ if (aProcessedEdges.find(aEExp.current()) != aProcessedEdges.end())
+ continue; // wire is already processed
+ // mark edges as processed
+ for (; aEExp.more(); aEExp.next())
+ aProcessedEdges.insert(aEExp.current());
+ // store the wire
+ theWires.push_back(aWExp.current());
+ }
+ }
+
+ // collect unused edges
+ ListOfShape aCopy;
+ for (ListOfShape::iterator anIt = aSketchEdges.begin(); anIt != aSketchEdges.end(); ++anIt) {
+ ListOfShape anImages;
+ aSketchBuilder->modified(*anIt, anImages);
+ for (ListOfShape::iterator anEdge = anImages.begin(); anEdge != anImages.end(); ++anEdge)
+ if (aProcessedEdges.find(*anEdge) == aProcessedEdges.end())
+ aCopy.push_back(*anEdge);
+ }
+
+ if (aCopy.size() > 1) {
+ // split these edges
+ std::shared_ptr<GeomAlgoAPI_PaveFiller> aGeneralFuse(new GeomAlgoAPI_PaveFiller(aCopy));
+ if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(
+ aGeneralFuse, BuildPlugin_Wire::ID(), theError))
+ return false;
+ anAlgoList->appendAlgo(aGeneralFuse);
+
+ // collect edges after the split
+ aSketchEdges.clear();
+ for (GeomAPI_ShapeExplorer anExp(aGeneralFuse->shape(), GeomAPI_Shape::EDGE);
+ anExp.more(); anExp.next())
+ aSketchEdges.push_back(anExp.current());
+ }
+ else
+ aSketchEdges = aCopy;
+ }
+
+ // connect least edges to wires
+ typedef std::list<ListOfShape> ListOfWires;
+ ListOfWires aNewWires;
+ typedef std::map<GeomVertexPtr, ListOfWires::iterator,
+ GeomAPI_Vertex::GeometricComparator> MapVertexWire;
+ MapVertexWire aMapVW;
+ for (ListOfShape::iterator aEIt = aSketchEdges.begin(); aEIt != aSketchEdges.end(); ++aEIt) {
+ GeomEdgePtr anEdge = (*aEIt)->edge();
+ GeomVertexPtr aStartV, aEndV;
+ anEdge->vertices(aStartV, aEndV);
+ MapVertexWire::iterator aFoundStart = aMapVW.find(aStartV);
+ MapVertexWire::iterator aFoundEnd = aMapVW.find(aEndV);
+ if (aFoundStart == aMapVW.end()) {
+ if (aFoundEnd == aMapVW.end()) {
+ // new wire
+ aNewWires.push_back(ListOfShape());
+ ListOfWires::iterator aNewW = --aNewWires.end();
+ aNewW->push_back(anEdge);
+ aMapVW[aStartV] = aNewW;
+ aMapVW[aEndV] = aNewW;
+ continue;
+ }
+ }
+ else {
+ if (aFoundEnd == aMapVW.end()) {
+ // swap found vertices for correct further processing
+ aFoundEnd = aFoundStart;
+ aStartV = aEndV;
+ }
+ else {
+ // both vertices are found => close the loop
+ aFoundStart->second->push_back(anEdge);
+ if (aFoundStart->second != aFoundEnd->second) {
+ aFoundStart->second->insert(aFoundStart->second->end(),
+ aFoundEnd->second->begin(), aFoundEnd->second->end());
+ aNewWires.erase(aFoundEnd->second);
+ }
+ aMapVW.erase(aFoundStart);
+ aMapVW.erase(aFoundEnd);
+ continue;
+ }
+ }
+ // add edge to existing wire, substitute the connection point
+ // by the other boundary point of the edge
+ aFoundEnd->second->push_back(anEdge);
+ aMapVW[aStartV] = aFoundEnd->second;
+ aMapVW.erase(aFoundEnd);
+ }
+
+ // generate new wires from the sets of edges
+ for (ListOfWires::iterator anIt = aNewWires.begin(); anIt != aNewWires.end(); ++anIt) {
+ GeomShapePtr aWire;
+ if (!buildWire(*anIt, aWire, theError))
+ return false;
+ theWires.push_back(aWire);
+ }
+
+ theAlgo = anAlgoList;
+ return true;
+}
return MY_ADD_CONTOUR_ACTION_ID;
}
+ /// Attribute name of "Compute intersections" checkbox.
+ inline static const std::string& INTERSECT_ID()
+ {
+ static const std::string MY_INTERSECT_ID("intersect");
+ return MY_INTERSECT_ID;
+ }
+
/// \return the kind of a feature.
BUILDPLUGIN_EXPORT virtual const std::string& getKind()
{
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Build</source>
+ <translation>Construire</translation>
+ </message>
+ <message>
+ <source>CompSolid</source>
+ <translation>Solide Composite</translation>
+ </message>
+ <message>
+ <source>Compound</source>
+ <translation>Assemblage</translation>
+ </message>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <source>Face</source>
+ <translation>Face</translation>
+ </message>
+ <message>
+ <source>Filling</source>
+ <translation>Remplissage</translation>
+ </message>
+ <message>
+ <source>Interpolation</source>
+ <translation>Interpolation</translation>
+ </message>
+ <message>
+ <source>Polyline</source>
+ <translation>Polyligne</translation>
+ </message>
+ <message>
+ <source>Shell</source>
+ <translation>Coque</translation>
+ </message>
+ <message>
+ <source>Solid</source>
+ <translation>Solide</translation>
+ </message>
+ <message>
+ <source>Sub-Shapes</source>
+ <translation>Sous-formes</translation>
+ </message>
+ <message>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ <message>
+ <source>Wire</source>
+ <translation>Contour</translation>
+ </message>
+ </context>
+
+ <!-- Validators -->
+
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Attribute have empty context.</source>
+ <translation>Objet sélectionné non valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty shape selected.</source>
+ <translation>Forme vide sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Les objets infinis ne sont pas acceptés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:first_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:second_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un deuxième point</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Face:BuildPlugin_ValidatorBaseForFace</name>
+ <message>
+ <source>Empty attribute \"%1\".</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ <message>
+ <source>Objects not selected.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ <message>
+ <source>Error while checking if edges intersects.</source>
+ <translation>Erreur lors de la vérification de l'intersection des arêtes.</translation>
+ </message>
+ <message>
+ <source>Selected objects have intersections.</source>
+ <translation>Les objets sélectionnés ont des intersections.</translation>
+ </message>
+ <message>
+ <source>Selected object(s) should belong to only one plane.</source>
+ <translation>Les objets sélectionnés doivent appartenir à un seul plan.</translation>
+ </message>
+ <message>
+ <source>Selected objects do not generate closed contour.</source>
+ <translation>Les objets sélectionnés ne génèrent pas un contour fermé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Attribute have empty context.</source>
+ <translation>Objet sélectionné non valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty shape selected.</source>
+ <translation>Forme vide sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Les objets infinis ne sont pas acceptés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Objet sélectionné non valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SubShapes:subshapes:BuildPlugin_ValidatorSubShapesSelection</name>
+ <message>
+ <source>Could not get selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:subshapes:BuildPlugin_ValidatorSubShapesSelection</name>
+ <message>
+ <source>Base shape is empty.</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:subshapes:BuildPlugin_ValidatorSubShapesSelection</name>
+ <message>
+ <source>Empty attribute in list.</source>
+ <translation>Objet sélectionné non valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:subshapes:BuildPlugin_ValidatorSubShapesSelection</name>
+ <message>
+ <source>Selected shape has unacceptable type.</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:subshapes:BuildPlugin_ValidatorSubShapesSelection</name>
+ <message>
+ <source>Selected shape is not inside base face.</source>
+ <translation>La forme sélectionnée n'est pas à l'intérieur de la base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_shape" is not initialized.</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "subshapes" is not initialized.</source>
+ <translation>Sous-formes non sélectionnées.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>La forme de base devrait être l’un des types suivants: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Objet sélectionné non valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Attribute have empty context.</source>
+ <translation>Objet sélectionné non valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty shape selected.</source>
+ <translation>Forme vide sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Les objets infinis ne sont pas acceptés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Wire:BuildPlugin_ValidatorBaseForWire</name>
+ <message>
+ <source>Empty attribute \"%1\".</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:BuildPlugin_ValidatorBaseForWire</name>
+ <message>
+ <source>Result wire empty. Probably it has disconnected edges or non-manifold.</source>
+ <translation>Résultat contour vide. Probablement il possède des bords déconnectés ou non-manifold.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection list.</source>
+ <translation>Impossible d'obtenir la liste de sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Could not get selection.</source>
+ <translation>Impossible d'obtenir la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Attribute have empty context.</source>
+ <translation>Les attributs ont un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty shape selected.</source>
+ <translation>Forme vide sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Les objets infinis ne sont pas acceptés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Filling:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Attribute "%1" should contain at least %2 items.</source>
+ <translation>La liste des segments et des contours doit contenir au moins 2 éléments.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Polyline:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Attribute "%1" should contain at least %2 items.</source>
+ <translation>La liste de points doit contenir au moins 2 éléments</translation>
+ </message>
+ </context>
+ <context>
+ <name>Model_Data</name>
+ <message>
+ <source>Error: Result polyline has self-intersections.</source>
+ <translation>La polyligne a des auto-intersections.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Polyline</name>
+ <message>
+ <source>Error: Result polyline has self-intersections.</source>
+ <translation>La polyligne a des auto-intersections.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Interpolation:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Attribute "%1" should contain at least %2 items.</source>
+ <translation>La liste de points doit contenir au moins 2 éléments</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:tangent_end</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le vecteur tangent à la fin de la courbe</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>CompSolid</name>
+ <message>
+ <source>CompSolid</source>
+ <translation>Solide Composite</translation>
+ </message>
+ <message>
+ <source>Create a compsolid from solids or other compsolids</source>
+ <translation>Créer un solide composite à partir de solides ou d'autres solides composites</translation>
+ </message>
+ </context>
+ <context>
+ <name>CompSolid:BuildPlugin_ValidatorBaseForSolids</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Liste de sélection vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>CompSolid:base_objects</name>
+ <message>
+ <source>Select solids or compsolids.</source>
+ <translation>Sélectionnez des solides ou des solides composites.</translation>
+ </message>
+ <message>
+ <source>Solids and CompSolids:</source>
+ <translation>Solides et Solides Composites:</translation>
+ </message>
+ </context>
+ <context>
+ <name>CompSolid:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Liste de sélection vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>CompSolid:BuildPlugin_ValidatorBaseForSolids</name>
+ <message>
+ <source>Unable to build a solid</source>
+ <translation>Impossible de créer un solide.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Compound</name>
+ <message>
+ <source>Compound</source>
+ <translation>Assemblage</translation>
+ </message>
+ <message>
+ <source>Create a compound of objects</source>
+ <translation>Créer un assemblage</translation>
+ </message>
+ </context>
+ <context>
+ <name>Compound:base_objects</name>
+ <message>
+ <source>Objects:</source>
+ <translation>Objets:</translation>
+ </message>
+ <message>
+ <source>Select any kind of objects.</source>
+ <translation>Sélectionnez n'importe quel type d'objets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Compound:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionner des objets de base.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Edge</name>
+ <message>
+ <source>Create edges from sketch edges or other edge objects</source>
+ <translation>Créer des arêtes à partir d'arêtes d'esquisse ou d'autres objets d'arête</translation>
+ </message>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:base_objects</name>
+ <message>
+ <source>Edges:</source>
+ <translation>Arêtes:</translation>
+ </message>
+ <message>
+ <source>Select edges on sketch or edges objects.</source>
+ <translation>Sélectionner des arêtes sur des objets d'esquisse ou d'arêtes.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:creation_method</name>
+ <message>
+ <source>By segments</source>
+ <translation>Par segments</translation>
+ </message>
+ <message>
+ <source>By two points</source>
+ <translation>Par deux points</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:first_point</name>
+ <message>
+ <source>First point</source>
+ <translation>Premier point</translation>
+ </message>
+ <message>
+ <source>Select a first point</source>
+ <translation>Sélectionnez un premier point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:first_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:second_point</name>
+ <message>
+ <source>Second point</source>
+ <translation>Deuxième point</translation>
+ </message>
+ <message>
+ <source>Select a second point</source>
+ <translation>Sélectionnez un deuxième point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Edge:second_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Face</name>
+ <message>
+ <source>Create a face from edges, wires and faces</source>
+ <translation>Créer une face à partir d'arêtes, de contours et de faces</translation>
+ </message>
+ <message>
+ <source>Face</source>
+ <translation>Face</translation>
+ </message>
+ </context>
+ <context>
+ <name>Face:base_objects</name>
+ <message>
+ <source>Objects:</source>
+ <translation>Objets:</translation>
+ </message>
+ <message>
+ <source>Select edges, wires or faces.</source>
+ <translation>Sélectionnez des arêtes, des contours ou des faces.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Filling</name>
+ <message>
+ <source>Create face from list of edges</source>
+ <translation>Créer une face à partir d'une liste d'arêtes</translation>
+ </message>
+ <message>
+ <source>Filling</source>
+ <translation>Remplissage</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:advanced_options</name>
+ <message>
+ <source>Advanced options</source>
+ <translation>Options avancées</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:approximation</name>
+ <message>
+ <source>Approximation</source>
+ <translation>Approximation</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:base_objects</name>
+ <message>
+ <source>Segments and wires:</source>
+ <translation>Segments et contours:</translation>
+ </message>
+ <message>
+ <source>Select edges or wires.</source>
+ <translation>Sélectionnez des arêtes ou des contours.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:max_degree</name>
+ <message>
+ <source>Max deg</source>
+ <translation>Max deg</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:min_degree</name>
+ <message>
+ <source>Min deg</source>
+ <translation>Min deg</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:nb_iter</name>
+ <message>
+ <source>Nb iter</source>
+ <translation>Nb iter</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:orientation</name>
+ <message>
+ <source>Auto-correct edges orientation</source>
+ <translation>Correction automatique de l'orientation des bords</translation>
+ </message>
+ <message>
+ <source>Use curve information</source>
+ <translation>Utiliser les informations de la courbe</translation>
+ </message>
+ <message>
+ <source>Use edges orientation</source>
+ <translation>Utiliser l'orientation des bords</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:tol_2d</name>
+ <message>
+ <source>Tol 2D</source>
+ <translation>Tol 2D</translation>
+ </message>
+ </context>
+ <context>
+ <name>Filling:tol_3d</name>
+ <message>
+ <source>Tol 3D</source>
+ <translation>Tol 3D</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Interpolation</name>
+ <message>
+ <source>Create an interpolation curve from points</source>
+ <translation>Créer une courbe d'interpolation à partir de points</translation>
+ </message>
+ <message>
+ <source>Interpolation</source>
+ <translation>Interpolation</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:base_objects</name>
+ <message>
+ <source>Points and vertices:</source>
+ <translation>Points et sommets:</translation>
+ </message>
+ <message>
+ <source>Select points or vertices objects.</source>
+ <translation>Sélectionner des points ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:closed</name>
+ <message>
+ <source>Closed</source>
+ <translation>Fermé</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:reorder</name>
+ <message>
+ <source>Changes the order of points to construct the shortest curve.</source>
+ <translation>Change l'ordre des points pour construire la courbe la plus courte.</translation>
+ </message>
+ <message>
+ <source>Reorder</source>
+ <translation>Réorganiser</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:tangent_end</name>
+ <message>
+ <source><end></source>
+ <translation><fin></translation>
+ </message>
+ <message>
+ <source>End</source>
+ <translation>Fin</translation>
+ </message>
+ <message>
+ <source>Select vector tangent to the end of curve</source>
+ <translation>Sélectionnez le vecteur tangent à la fin de la courbe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:tangent_start</name>
+ <message>
+ <source><start></source>
+ <translation><début></translation>
+ </message>
+ <message>
+ <source>Select vector tangent to the start of curve</source>
+ <translation>Sélectionnez le vecteur tangent au début de la courbe</translation>
+ </message>
+ <message>
+ <source>Start</source>
+ <translation>Début</translation>
+ </message>
+ </context>
+ <context>
+ <name>Interpolation:use_tangents</name>
+ <message>
+ <source>Tangents</source>
+ <translation>Tangentes</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Polyline</name>
+ <message>
+ <source>Create a polyline from points</source>
+ <translation>Créer une polyligne à partir de points</translation>
+ </message>
+ <message>
+ <source>Polyline</source>
+ <translation>Polyligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>Polyline:base_objects</name>
+ <message>
+ <source>Points and vertices:</source>
+ <translation>Points et sommets:</translation>
+ </message>
+ <message>
+ <source>Select points or vertices objects.</source>
+ <translation>Sélectionner des points ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Polyline:closed</name>
+ <message>
+ <source>Closed</source>
+ <translation>Fermé</translation>
+ </message>
+ <message>
+ <source>Closes the polyline.</source>
+ <translation>Ferme la polyligne.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Shell</name>
+ <message>
+ <source>Create a shell from faces or shells objects</source>
+ <translation>Créer une coque à partir d'objets faces ou coques</translation>
+ </message>
+ <message>
+ <source>Shell</source>
+ <translation>Coque</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects</name>
+ <message>
+ <source>Faces and shells:</source>
+ <translation>Faces et coques:</translation>
+ </message>
+ <message>
+ <source>Select faces or shells objects.</source>
+ <translation>Sélectionner des objets faces ou coques.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Shell:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Liste de sélection vide.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Solid</name>
+ <message>
+ <source>Create a solid from faces or shells</source>
+ <translation>Créer un solide à partir de faces ou de coques</translation>
+ </message>
+ <message>
+ <source>Solid</source>
+ <translation>Solide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Solid:BuildPlugin_ValidatorBaseForSolids</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Liste de sélection vide.</translation>
+ </message>
+ <message>
+ <source>Unable to build a solid</source>
+ <translation>Impossible de construire un solide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Solid:base_objects</name>
+ <message>
+ <source>Faces and shells:</source>
+ <translation>Faces et coques:</translation>
+ </message>
+ <message>
+ <source>Select faces or shells.</source>
+ <translation>Sélectionnez des faces ou des coques.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Solid:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
+ <message>
+ <source>Empty selection list.</source>
+ <translation>Liste de sélection vide.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SubShapes</name>
+ <message>
+ <source>Allows to add or to remove sub-shapes of the selected shape</source>
+ <translation>Permet d'ajouter ou de supprimer des sous-formes de la forme sélectionnée</translation>
+ </message>
+ <message>
+ <source>Sub-Shapes</source>
+ <translation>Sous-formes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:base_shape</name>
+ <message>
+ <source>Select a shape to modify.</source>
+ <translation>Sélectionnez une forme à modifier.</translation>
+ </message>
+ <message>
+ <source>Shape:</source>
+ <translation>Forme:</translation>
+ </message>
+ </context>
+ <context>
+ <name>SubShapes:subshapes</name>
+ <message>
+ <source>Select shapes on sketch to add.</source>
+ <translation>Sélectionnez des formes sur l'esquisse à ajouter.</translation>
+ </message>
+ <message>
+ <source>Sub-Shapes:</source>
+ <translation>Sous-formes:</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Vertex</name>
+ <message>
+ <source>Create vertices from sketch point or other vertex objects</source>
+ <translation>Créer des sommets à partir d'un point d'esquisse ou d'autres objets de sommet</translation>
+ </message>
+ <message>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ </context>
+ <context>
+ <name>Vertex:base_objects</name>
+ <message>
+ <source>Select vertices on sketch or vertex objects.</source>
+ <translation>Sélectionnez des sommets de l'esquisse ou des objets sommet.</translation>
+ </message>
+ <message>
+ <source>Vertices:</source>
+ <translation>Sommets:</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Wire</name>
+ <message>
+ <source>Create a wire from sketch edges, edges and wires objects</source>
+ <translation>Créer un contour à partir d'arêtes de l’esquisse, d'arêtes et de contours</translation>
+ </message>
+ <message>
+ <source>Wire</source>
+ <translation>Contour</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:add_contour</name>
+ <message>
+ <source>Add contour</source>
+ <translation>Ajouter un contour</translation>
+ </message>
+ <message>
+ <source>Adds to the list of segments other segments of the sketcher connected to the already selected ones to create a closed contour.</source>
+ <translation>Ajoute à la liste des segments d'autres segments de l'esquisse connectés à ceux déjà sélectionnés pour créer un contour fermé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Wire:base_objects</name>
+ <message>
+ <source>Segments and wires:</source>
+ <translation>Segments et contours:</translation>
+ </message>
+ <message>
+ <source>Select edges on sketch, edges or wires objects.</source>
+ <translation>Sélectionner des arêtes sur des objets d'esquisse, d'arêtes ou de contours.</translation>
+ </message>
+ </context>
+
+</TS>
${PROJECT_SOURCE_DIR}/src/ModelAPI
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
+ ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
${PROJECT_SOURCE_DIR}/src/GeomValidators
+ ${PROJECT_SOURCE_DIR}/src/SketchPlugin
)
SET(PROJECT_HEADERS
SET(TEXT_RESOURCES
BuildPlugin_msg_en.ts
+ BuildPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
ADD_UNIT_TESTS(TestVertex.py
TestVertex_ErrorMsg.py
+ TestVertex_WholeSketch_1.py
+ TestVertex_WholeSketch_2.py
TestEdge.py
TestEdge_ByPoints.py
TestEdge_ErrorMsg.py
+ TestEdge_WholeSketch_1.py
+ TestEdge_WholeSketch_2.py
+ TestEdge_WholeSketch_3.py
+ TestEdge_WholeSketch_4.py
TestWire.py
TestWire_ErrorMsg.py
+ TestWire_WholeSketch_1.py
+ TestWire_WholeSketch_2.py
+ TestWire_WholeSketch_3.py
+ TestWire_WholeSketch_4.py
+ TestWire_WholeSketch_5.py
+ TestWire_WholeSketch_6.py
TestPolyline.py
TestInterpolation.py
TestFace.py
TestFace_ErrorMsg.py
+ TestFace_WholeSketch_1.py
+ TestFace_WholeSketch_2.py
TestShell.py
+ TestShell_WholeSketch_1.py
+ TestShell_WholeSketch_2.py
TestSolid.py
TestSolid_ErrorMsg.py
TestCompSolid.py
aSession.startOperation()
anEdgeFeature3 = aPart.addFeature("Edge")
aBaseObjectsList = anEdgeFeature3.selectionList("base_objects")
-aBaseObjectsList.append(aSketchResult, None)
-aSession.finishOperation()
-assert (len(anEdgeFeature3.results()) == 0)
-
-aSession.startOperation()
-aBaseObjectsList.clear()
aShapeExplorer = GeomAPI_ShapeExplorer(aBoxShape, GeomAPI_Shape.VERTEX)
aShape = aShapeExplorer.current()
aBaseObjectsList.append(aBoxResult, aShape)
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], False)
+model.end()
+
+model.testNbResults(Edge_1, 4)
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1])
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], True)
+model.end()
+
+model.testNbResults(Edge_1, 8)
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1, 1, 1, 1, 1])
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2, 2, 2, 2, 2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "Sketch_1"), model.selection("EDGE", "Sketch_2/SketchArc_1_2")], False)
+model.end()
+
+model.testNbResults(Edge_1, 4)
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1])
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("COMPOUND", "Sketch_1"), model.selection("EDGE", "Sketch_2/SketchArc_1_2")], True)
+model.end()
+
+model.testNbResults(Edge_1, 8)
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.EDGE, [1, 1, 1, 1, 1, 1, 1, 1])
+model.testNbSubShapes(Edge_1, GeomAPI_Shape.VERTEX, [2, 2, 2, 2, 2, 2, 2, 2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-5, 10, 20)
+SketchLine_4 = Sketch_2.addLine(-25, 10, 15, 10)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchCircle_1.results()[1])
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")])
+model.end()
+
+model.testNbResults(Face_1, 1)
+model.testNbSubShapes(Face_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Face_1, GeomAPI_Shape.EDGE, [3])
+model.testNbSubShapes(Face_1, GeomAPI_Shape.VERTEX, [6])
+model.testResultsVolumes(Face_1, [441.0539215686274])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-5, 10, 20)
+SketchLine_4 = Sketch_2.addLine(-25, 10, 15, 10)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchCircle_1.results()[1])
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")])
+model.end()
+
+model.testNbResults(Face_1, 3)
+model.testNbSubShapes(Face_1, GeomAPI_Shape.FACE, [1, 1, 1])
+model.testNbSubShapes(Face_1, GeomAPI_Shape.EDGE, [3, 2, 2])
+model.testNbSubShapes(Face_1, GeomAPI_Shape.VERTEX, [6, 4, 4])
+model.testResultsVolumes(Face_1, [441.0539215686274, 628.318530717958, 628.318530717958])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-5, 10, 20)
+SketchLine_4 = Sketch_2.addLine(-25, 10, 15, 10)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchCircle_1.results()[1])
+model.do()
+Shell_1 = model.addShell(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")])
+model.end()
+
+model.testNbResults(Shell_1, 1)
+model.testNbSubShapes(Shell_1, GeomAPI_Shape.FACE, [1])
+model.testNbSubShapes(Shell_1, GeomAPI_Shape.EDGE, [3])
+model.testNbSubShapes(Shell_1, GeomAPI_Shape.VERTEX, [6])
+model.testResultsVolumes(Shell_1, [441.0539215686274])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-5, 10, 20)
+SketchLine_4 = Sketch_2.addLine(-25, 10, 15, 10)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_4.startPoint(), SketchCircle_1.results()[1])
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_4.endPoint(), SketchCircle_1.results()[1])
+model.do()
+Shell_1 = model.addShell(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")])
+model.end()
+
+model.testNbResults(Shell_1, 2)
+model.testNbSubShapes(Shell_1, GeomAPI_Shape.FACE, [1, 2])
+model.testNbSubShapes(Shell_1, GeomAPI_Shape.EDGE, [3, 4])
+model.testNbSubShapes(Shell_1, GeomAPI_Shape.VERTEX, [6, 8])
+model.testResultsVolumes(Shell_1, [441.0539215686274, 1256.637061435917])
+
+assert(model.checkPythonDump())
# Test results
assert (len(aVertexFeature.results()) == aNumOfPoints)
-# Check Vertex feature failed on incorrect input
+# Check Vertex feature correct on a whole sketch
aSession.startOperation()
aVertexFeature2 = aPart.addFeature("Vertex")
aBaseObjectsList = aVertexFeature2.selectionList("base_objects")
aBaseObjectsList.append(aSketchResult, None)
aSession.finishOperation()
-assert (len(aVertexFeature2.results()) == 0)
+assert (len(aVertexFeature2.results()) == aNumOfPoints)
+# Check Vertex feature failed on incorrect input
aSession.startOperation()
aLine = aSketchFeature.addFeature("SketchLine")
geomDataAPI_Point2D(aLine.attribute("StartPoint")).setValue(0, 0)
geomDataAPI_Point2D(aLine.attribute("EndPoint")).setValue(100, 100)
aSession.finishOperation()
aSession.startOperation()
-aBaseObjectsList.clear()
+aPart.setCurrentFeature(aVertexFeature2, False)
+aSession.finishOperation()
+aSession.startOperation()
+aVertexFeature3 = aPart.addFeature("Vertex")
+aBaseObjectsList = aVertexFeature3.selectionList("base_objects")
aBaseObjectsList.append(aSketchResult, aLine.lastResult().shape())
aSession.finishOperation()
-assert (len(aVertexFeature2.results()) == 0)
+assert (len(aVertexFeature3.results()) == 0)
# remove failed feature
aSession.startOperation()
-aPart.removeFeature(aVertexFeature2)
-aPart.setCurrentFeature(aVertexFeature, True)
+aPart.removeFeature(aVertexFeature3)
aSession.finishOperation()
from salome.shaper import model
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], False)
+model.end()
+
+model.testNbResults(Vertex_1, 7)
+model.testNbSubShapes(Vertex_1, GeomAPI_Shape.VERTEX, [1, 1, 1, 1, 1, 1, 1])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Vertex_1 = model.addVertex(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], True)
+model.end()
+
+model.testNbResults(Vertex_1, 9)
+model.testNbSubShapes(Vertex_1, GeomAPI_Shape.VERTEX, [1, 1, 1, 1, 1, 1, 1, 1, 1])
+
+assert(model.checkPythonDump())
assert (len(aWireFeature2.results()) == 1)
# =============================================================================
-# Test 4. Check Wire feature failed on incorrect input
+# Test 4. Check Wire feature on the whole sketch
# =============================================================================
aSession.startOperation()
aBaseObjectsList = aWireFeature3.selectionList("base_objects")
aBaseObjectsList.append(aSketchResult, None)
aSession.finishOperation()
-assert (len(aWireFeature3.results()) == 0)
+assert (len(aWireFeature3.results()) == 1)
+
+# =============================================================================
+# Test 5. Check Wire feature failed on incorrect input
+# =============================================================================
aSession.startOperation()
-aBaseObjectsList.clear()
+aWireFeature3 = aPart.addFeature("Wire")
+aBaseObjectsList = aWireFeature3.selectionList("base_objects")
aShapeExplorer = GeomAPI_ShapeExplorer(aBoxShape, GeomAPI_Shape.VERTEX)
aShape = aShapeExplorer.current()
aBaseObjectsList.append(aBoxResult, aShape)
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], False)
+model.end()
+
+model.testNbResults(Wire_1, 2)
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [3, 1])
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [6, 2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(0, -20, 45, -15)
+SketchLine_2 = Sketch_1.addLine(45, -15, 10, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(10, 15, 25, -40)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchArc_1 = Sketch_2.addArc(-5, 10, -5, -10, 15, 10, False)
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1"), model.selection("COMPOUND", "Sketch_2")], True)
+model.end()
+
+model.testNbResults(Wire_1, 3)
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [3, 2, 1])
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [6, 4, 2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20.12530657814797, -34.87380706737215, -10.13449613893172, -4.005160196312613)
+SketchLine_2 = Sketch_1.addLine(-15.5320876476665, -20.68212021382587, -37.87121169090271, -18.01751586506584)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result())
+SketchLine_3 = Sketch_1.addLine(-37.87121169090271, -18.01751586506584, -28.23126689685475, -46.70782775211335)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-10.13449613893172, -4.005160196312613, -17.3289483797767, 22.37844327189705)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -36.60883796787262, 2.754269941156556)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-36.60883796787262, 2.754269941156556, -10.13449613893172, -4.005160196312613)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")])
+model.end()
+
+model.testNbResults(Wire_1, 2)
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [4, 2])
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [8, 4])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20.12530657814797, -34.87380706737215, -10.13449613893172, -4.005160196312613)
+SketchLine_2 = Sketch_1.addLine(-15.5320876476665, -20.68212021382587, -37.87121169090271, -18.01751586506584)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result())
+SketchLine_3 = Sketch_1.addLine(-37.87121169090271, -18.01751586506584, -28.23126689685475, -46.70782775211335)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-10.13449613893172, -4.005160196312613, -17.3289483797767, 22.37844327189705)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -36.60883796787262, 2.754269941156556)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-36.60883796787262, 2.754269941156556, -10.13449613893172, -4.005160196312613)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_6.endPoint())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], True)
+model.end()
+
+model.testNbResults(Wire_1, 3)
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [3, 2, 2])
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [6, 4, 4])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20.13297844091623, -34.87132400696332, -10.14115693918956, -4.003004374441855)
+SketchLine_2 = Sketch_1.addLine(-15.36017779982175, -20.12643132586926, -37.81263639928755, -17.52358908612689)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result())
+SketchLine_3 = Sketch_1.addLine(-37.81263639928755, -17.52358908612689, -28.23126689685475, -46.70782775211335)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-10.14115693918956, -4.003004374441855, -17.3289483797767, 22.37844327189705)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -39.00238825664131, 1.575954908729718)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-39.00238825664131, 1.575954908729718, -25.86766799285223, -18.90833134866903)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_2.result())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")])
+model.end()
+
+model.testNbResults(Wire_1, 2)
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [4, 2])
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [8, 4])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20.13297844091623, -34.87132400696332, -10.14115693918956, -4.003004374441855)
+SketchLine_2 = Sketch_1.addLine(-15.36017779982175, -20.12643132586926, -37.81263639928755, -17.52358908612689)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_1.result())
+SketchLine_3 = Sketch_1.addLine(-37.81263639928755, -17.52358908612689, -28.23126689685475, -46.70782775211335)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(-10.14115693918956, -4.003004374441855, -17.3289483797767, 22.37844327189705)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(-17.3289483797767, 22.37844327189705, -39.00238825664131, 1.575954908729718)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchLine_6 = Sketch_1.addLine(-39.00238825664131, 1.575954908729718, -25.86766799285223, -18.90833134866903)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchLine_2.result())
+model.do()
+Wire_1 = model.addWire(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], True)
+model.end()
+
+model.testNbResults(Wire_1, 3)
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.EDGE, [5, 1, 2])
+model.testNbSubShapes(Wire_1, GeomAPI_Shape.VERTEX, [10, 2, 4])
+
+assert(model.checkPythonDump())
.. image:: images/edge_by_segments_32x32.png
:align: left
-**By edges** creates edges using already existing edges in other shapes.
+**By edges** creates edges using already existing edges in other shapes or full sketches.
.. image:: images/edge_by_points_32x32.png
:align: left
.. centered::
Create by edges
-Select one or several edges in the viewer.
+Select one or several edges in the viewer. Also, the full sketch can be selected. In this case, all edges of the sketch will be processed.
+Checkbox **Compute intersections** forces to split sketch edges in the points of intersection.
**Apply** button creates edges.
**TUI Command**:
-.. py:function:: model.addEdge(Part_doc, Shapes)
+.. py:function:: model.addEdge(Part_doc, Shapes, Intersect)
:param part: The current part object.
:param list: A list of shapes.
+ :param bool: Split edges by intersection points. False by default.
:return: Result object.
Result
Select one or several faces in viewer. Additionally, a face can be build by a closed wire or a set of edges composing a closed wire.
+It also allowed to select a whole sketch result from the object browser. In this case, the smallest closed contour of the sketch will be transformed to the planar face.
+
**Apply** button creates faces.
**Cancel** button cancels the operation.
.. centered::
Create a shell
-Select one or several faces in the viewer.
+Select one or several faces in the viewer. Additionally, it is allowed to select a whole sketch result from the object browser. In this case, the result shell will contain faces corresponding to all smallest closed contours of the sketch.
**Apply** button creates a shell.
.. centered::
Create vertices
-Select one or several vertices in the viewer.
+Select one or several vertices in the viewer. It also allowed to select a whole sketch result in the object browser, then all start and end points of the sketch segments will be added into result. Checkbox **Compute intersections** forces to include intersection vertices of edges of the selected sketch.
**Apply** button creates vertices.
**TUI Command**:
-.. py:function:: model.addVertex(Part_doc, Shapes)
+.. py:function:: model.addVertex(Part_doc, Shapes, Intersect)
:param part: The current part object.
:param list: A list of shapes.
+ :param bool: Intersect edges (applicable for sketch only). False by default.
:return: Result object.
Result
Select one or several edges in the viewer. For automatic selection of a closed contour starting from the selected edge it is necessary to press **Add contour** button.
+Moreover, the full sketch can be selected. In this case, a set of wires is composed using edges of the sketch.
+Checkbox **Compute intersections** forces to split sketch edges in the points of intersection.
+
**Apply** button creates a wire.
**Cancel** button cancels the operation.
**TUI Command**:
-.. py:function:: model.addWire(Part_doc, Shapes)
+.. py:function:: model.addWire(Part_doc, Shapes, Intersect)
:param part: The current part object.
:param list: A list of shapes.
+ :param bool: Split edges by intersection points. False by default.
:return: Result object.
Result
<toolbox id="creation_method">
<box id="by_segments" title="By segments" icon="icons/Build/edge_by_segments_32x32.png">
<multi_selector id="base_objects"
- label="Edges:"
+ label="Edges or sketches:"
tooltip="Select edges on sketch or edges objects."
shape_types="edges"
concealment="true">
- <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge"/>
+ <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,compound"/>
</multi_selector>
+ <boolvalue id="intersect" label="Compute intersections" tooltip="Divide sketch edges in intersection points." default="false"/>
+ <validator id="BuildPlugin_ValidatorBaseForWire" parameters="base_objects,edge"/>
</box>
<box id="by_points" title="By two points" icon="icons/Build/edge_by_points_32x32.png">
<shape_selector id="first_point"
tooltip="Select edges, wires or faces."
shape_types="edges wires faces"
concealment="true">
- <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire,face"/>
+ <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire,face,compound"/>
</multi_selector>
<validator id="BuildPlugin_ValidatorBaseForFace" parameters="base_objects"/>
</source>
tooltip="Select faces or shells objects."
shape_types="faces shells"
concealment="true">
- <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell"/>
+ <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="face,shell,compound"/>
</multi_selector>
</source>
<source>
<multi_selector id="base_objects"
- label="Vertices:"
- tooltip="Select vertices on sketch or vertex objects."
- shape_types="vertices"
+ label="Vertices and sketches:"
+ tooltip="Select vertices or sketch objects or features."
+ shape_types="vertices objects"
concealment="true">
+ <validator id="BuildPlugin_ValidatorBaseForVertex"/>
</multi_selector>
+ <boolvalue id="intersect" label="Compute intersections" tooltip="Compute intersections of all sketch edges." default="false"/>
</source>
tooltip="Select edges on sketch, edges or wires objects."
shape_types="edges wires"
concealment="true">
- <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire"/>
+ <validator id="BuildPlugin_ValidatorBaseForBuild" parameters="edge,wire,compound"/>
</multi_selector>
+ <boolvalue id="intersect" label="Compute intersections" tooltip="Divide sketch edges in intersection points." default="false"/>
<action id="add_contour"
label="Add contour"
tooltip="Adds to the list of segments other segments of the sketcher
connected to the already selected ones to create a closed contour."/>
- <validator id="BuildPlugin_ValidatorBaseForWire" parameters="base_objects"/>
+ <validator id="BuildPlugin_ValidatorBaseForWire" parameters="base_objects,wire"/>
</source>
SET(TEXT_RESOURCES
CollectionPlugin_msg_en.ts
+ CollectionPlugin_msg_fr.ts
)
# sources / moc wrappings
TestGroupWholeResult1.py
TestGroupWholeResult2.py
Test3031.py
+ TestGroupWholeFeature1.py
+ TestGroupWholeFeature2.py
+ TestGroupMoveAndSplit1.py
+ TestGroupMoveAndSplit2.py
+ TestGroupMoveAndSplit3.py
)
#include <ModelAPI_AttributeInteger.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeIntArray.h>
#include <ModelAPI_ResultGroup.h>
+#include <ModelAPI_Tools.h>
+#include <sstream>
CollectionPlugin_Group::CollectionPlugin_Group()
{
setResult(aGroup);
}
}
+
+// returns name with suffix, not existing in the existing set
+static std::string findName(
+ const std::string theOrigin, int& theSuffix, std::set<std::string>& theExisting)
+{
+ std::string aRes;
+ do {
+ std::ostringstream aName;
+ aName<<theOrigin<<"_"<<theSuffix;
+ aRes = aName.str();
+ theSuffix++;
+ } while(theExisting.count(aRes));
+ theExisting.insert(aRes);
+ return aRes;
+
+}
+
+bool CollectionPlugin_Group::customAction(const std::string& theActionId)
+{
+ if (theActionId == "split") {
+ DocumentPtr aDoc = document();
+ // collect all existing names of features to give unique names
+ std::set<std::string> aFeatNames, aResNames;
+ std::list<FeaturePtr> allFeat = aDoc->allFeatures();
+ std::list<FeaturePtr>::iterator allFeatIter = allFeat.begin();
+ for(; allFeatIter != allFeat.end(); allFeatIter++) {
+ FeaturePtr aFeat = *allFeatIter;
+ if (aFeat->data().get() && aFeat->data()->isValid()) {
+ aFeatNames.insert(aFeat->name());
+ if (aFeat->getKind() == ID() && aFeat->data().get() && aFeat->data()->isValid()) {
+ std::list<ResultPtr>::const_iterator aRess = aFeat->results().cbegin();
+ for(; aRess != aFeat->results().cend(); aRess++) {
+ ResultPtr aRes = *aRess;
+ if (aRes->data().get() && aRes->data()->isValid()) {
+ aResNames.insert(aRes->data()->name());
+ }
+ }
+ }
+ }
+ }
+
+ AttributeSelectionListPtr aList = selectionList(LIST_ID());
+ std::set<int> aRemoved;
+ bool aStay = false; // to indicate that the good attribute found stays in the list
+ int anIndex = 1; // index of the name assigned to group-feature and result
+ // added in the order: 3 2 1 orig=0, so, keep the results to give names later
+ std::list<ObjectPtr> aResults;
+ for(int aNext = aList->size() - 1; aNext >= 0; aNext--) {
+ AttributeSelectionPtr anOldAttr = aList->value(aNext);
+ if (anOldAttr->isInvalid() || !anOldAttr->context().get()) {// remove invalids
+ aRemoved.insert(aNext);
+ continue;
+ }
+ if (!aStay) {
+ aStay = true;
+ continue;
+ }
+ aRemoved.insert(aNext);
+ FeaturePtr aNew = aDoc->addFeature(ID(), false);
+ AttributeSelectionListPtr aNewList = aNew->selectionList(LIST_ID());
+ aNewList->setSelectionType(aList->selectionType());
+ aNewList->append(anOldAttr->contextObject(), anOldAttr->value());
+ aNew->execute();
+ aResults.push_front(aNew); // to keep the order
+ }
+ aResults.push_back(data()->owner());
+ // remove all selections except the first
+ aList->remove(aRemoved);
+ // set names
+ if (aResults.size() > 1) { // rename if there are new groups appeared only
+ std::list<ObjectPtr>::iterator aResIter = aResults.begin();
+ for(int aSuffix = 1; aResIter != aResults.end(); aResIter++) {
+ FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(*aResIter);
+ aFeat->data()->setName(findName(name(), aSuffix, aFeatNames));
+ if (!aFeat->results().empty() && !results().empty()) {
+ int aResSuf = aSuffix - 1;
+ std::string aResName = findName(firstResult()->data()->name(), aResSuf, aResNames);
+ aFeat->firstResult()->data()->setName(aResName);
+ ModelAPI_Tools::copyVisualizationAttrs(firstResult(), aFeat->firstResult());
+ }
+ }
+ // remove also filters if split performed
+ FiltersFeaturePtr aFilters = aList->filters();
+ if (aFilters.get()) {
+ std::list<std::string> aFiltersList = aFilters->filters();
+ std::list<std::string>::iterator aFilterName = aFiltersList.begin();
+ for(; aFilterName != aFiltersList.end(); aFilterName++) {
+ aFilters->removeFilter(*aFilterName);
+ }
+ }
+ }
+ }
+ return true;
+}
/// Use plugin manager for features creation
CollectionPlugin_Group();
+ /// Used for the split action of the group (Move to the end and split)
+ COLLECTIONPLUGIN_EXPORT virtual bool customAction(const std::string& theActionId);
};
#endif
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Field</source>
+ <translation>Champ</translation>
+ </message>
+ <message>
+ <source>Group</source>
+ <translation>Groupe</translation>
+ </message>
+ <message>
+ <source>Group Addition</source>
+ <translation>Addition de groupes</translation>
+ </message>
+ <message>
+ <source>Group Intersection</source>
+ <translation>Intersection de groupes</translation>
+ </message>
+ <message>
+ <source>Group Substraction</source>
+ <translation>Soustraction de groupes</translation>
+ </message>
+ </context>
+
+ <!-- Field -->
+ <context>
+ <name>Field</name>
+ <message>
+ <source>Create fields for selected shapes</source>
+ <translation>Créer des champs pour les formes sélectionnées</translation>
+ </message>
+ <message>
+ <source>Field</source>
+ <translation>Champ</translation>
+ </message>
+ </context>
+ <context>
+ <name>Field:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "components_names" is not initialized.</source>
+ <translation>Les composants ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>Field:CollectionPlugin_FieldValidator</name>
+ <message>
+ <source>Selection list is not initialized</source>
+ <translation>La liste de sélection n'est pas initialisée</translation>
+ </message>
+ </context>
+
+ <!-- Group -->
+ <context>
+ <name>Group</name>
+ <message>
+ <source>Create named collection of geometry entities</source>
+ <translation>Créer une collection nommée d'entités géométriques</translation>
+ </message>
+ <message>
+ <source>Group</source>
+ <translation>Groupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Group:group_list</name>
+ <message>
+ <source>Select a set of objects</source>
+ <translation>Sélectionnez un ensemble d'objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Group:group_list:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Context is empty.</source>
+ <translation>L'objet sélectionné a un contexte vide.</translation>
+ </message>
+ <message>
+ <source>Error: Result construction selected.</source>
+ <translation>Constructions non autorisées pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Group:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "group_list" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Group:name</name>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Please input the group name</source>
+ <translation>S'il vous plaît entrer le nom du groupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Group:group_list</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ensemble d'objets.</translation>
+ </message>
+ </context>
+
+ <!-- GroupAddition -->
+ <context>
+ <name>GroupAddition</name>
+ <message>
+ <source>Group Addition</source>
+ <translation>Addition de groupes</translation>
+ </message>
+ <message>
+ <source>Join several groups to single group</source>
+ <translation>Joindre plusieurs groupes pour former un seul groupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupAddition:group_list</name>
+ <message>
+ <source>Base groups:</source>
+ <translation>Groupes de base:</translation>
+ </message>
+ <message>
+ <source>Select a set of groups</source>
+ <translation>Sélectionnez un ensemble de groupes</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupAddition:name</name>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Please input the group name</source>
+ <translation>S'il vous plaît entrer le nom du groupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupAddition:group_list</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ensemble de groupes.</translation>
+ </message>
+ </context>
+
+ <!-- GroupIntersection -->
+ <context>
+ <name>GroupIntersection</name>
+ <message>
+ <source>Get elements existing in all groups</source>
+ <translation>Obtenir les éléments existants dans tous les groupes</translation>
+ </message>
+ <message>
+ <source>Group Intersection</source>
+ <translation>Intersection de groupes</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupIntersection:EmptyResult</name>
+ <message>
+ <source>Error: Empty result.</source>
+ <translation>Erreur : résultat vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupIntersection:group_list</name>
+ <message>
+ <source>Base groups:</source>
+ <translation>Groupes de base:</translation>
+ </message>
+ <message>
+ <source>Select a set of groups</source>
+ <translation>Sélectionnez un ensemble de groupes</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupIntersection:name</name>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Please input the group name</source>
+ <translation>S'il vous plaît entrer le nom du groupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupIntersection:group_list</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ensemble de groupes.</translation>
+ </message>
+ </context>
+
+ <!-- GroupSubstraction -->
+ <context>
+ <name>GroupSubstraction</name>
+ <message>
+ <source>Exclude elements existing tool groups</source>
+ <translation>Exclure des éléments des groupes d'outils existants</translation>
+ </message>
+ <message>
+ <source>Group Substraction</source>
+ <translation>Soustraction de groupes</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupSubstraction:group_list</name>
+ <message>
+ <source>Main groups:</source>
+ <translation>Groupes principaux:</translation>
+ </message>
+ <message>
+ <source>Select a set of groups</source>
+ <translation>Sélectionnez un ensemble de groupes</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupSubstraction:name</name>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Please input the group name</source>
+ <translation>S'il vous plaît entrer le nom du groupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupSubstraction:tools_list</name>
+ <message>
+ <source>Select a set of groups</source>
+ <translation>Sélectionnez un ensemble de groupes</translation>
+ </message>
+ <message>
+ <source>Tool groups:</source>
+ <translation>Groupes d'outils:</translation>
+ </message>
+ </context>
+ <context>
+ <name>GroupSubstraction:group_list</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ensemble de groupes.</translation>
+ </message>
+ </context>
+
+</TS>
--- /dev/null
+# Copyright (C) 2014-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
+#
+
+# Check the specification case of move to the end and split (#3059)
+
+from salome.shaper import model
+from ModelAPI import *
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 12, 0)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(33.32502963835739, 19.24021483244179, 5)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 5)
+SketchLine_1 = Sketch_1.addLine(0, 0, 33.32502963835739, 19.24021483244179)
+SketchLine_1.setAuxiliary(True)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchPoint_1.result())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_1.endPoint())
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_2.result(), SketchLine_1.result(), 30)
+Extrusion_1.setNestedSketch(Sketch_1)
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("FACE", "Extrusion_1_1/To_Face")])
+AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OZ"), 12)
+model.do()
+Part_1_doc.moveFeature(Group_1.feature(), AngularCopy_1.feature(), True)
+model.end()
+
+# must be created 12 groups of faces, 12 results
+assert(Part_1_doc.size("Groups") == 12)
+
+for i in range(12):
+ resShape = modelAPI_Result(Part_1_doc.object("Groups", i)).shape()
+ assert(not resShape.isNull())
+ # the group result is a compund, check that this is a compound of one face
+ aShapeExplorer = GeomAPI_ShapeExplorer(resShape, GeomAPI_Shape.FACE)
+ assert(aShapeExplorer.more())
+ assert(aShapeExplorer.current().isFace())
+ aShapeExplorer.next()
+ assert(not aShapeExplorer.more())
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-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
+#
+
+# Check the movement to the end and split: move to intermediate position, no duplicates appeared
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, "Edges", [model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]")])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 5, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"), False)
+SketchCircle_2 = SketchProjection_2.createdFeature()
+SketchCircle_3 = Sketch_2.addCircle(0, 10, 3)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchCircle_2.results()[1], SketchCircle_3.center())
+SketchCircle_4 = Sketch_2.addCircle(0, -10, 3)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchCircle_2.results()[1], SketchCircle_4.center())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), True)
+SketchLine_1 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchCircle_3.center(), SketchLine_1.result())
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchCircle_4.center(), SketchLine_1.result())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_3.results()[1], 3)
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchCircle_3.results()[1], SketchCircle_4.results()[1])
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+
+ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 3, [model.selection("SOLID", "ExtrusionCut_1_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face"))
+SketchLine_2 = Sketch_3.addLine(10, 2, -10, 2)
+SketchLine_3 = Sketch_3.addLine(-10, 2, -10, -2)
+SketchLine_4 = Sketch_3.addLine(-10, -2, 10, -2)
+SketchLine_5 = Sketch_3.addLine(10, -2, 10, 2)
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_2.result())
+SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_3.result())
+SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_4.result())
+SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_5.result())
+SketchProjection_4 = Sketch_3.addProjection(model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face])2(ExtrusionCut_1_1/Generated_Edge&ExtrusionCut_1_1/From_Face_1)2([ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchCircle_4_2])2"), False)
+SketchArc_1 = SketchProjection_4.createdFeature()
+SketchConstraintTangent_1 = Sketch_3.setTangent(SketchLine_5.result(), SketchArc_1.results()[1])
+SketchProjection_5 = Sketch_3.addProjection(model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchCircle_4_2])(ExtrusionCut_1_1/Generated_Edge&ExtrusionCut_1_1/From_Face_3)2(ExtrusionCut_1_1/Generated_Edge&ExtrusionCut_1_1/From_Face_2)2([ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchCircle_4_2][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face_3])2"), False)
+SketchArc_2 = SketchProjection_5.createdFeature()
+SketchConstraintTangent_2 = Sketch_3.setTangent(SketchArc_2.results()[1], SketchLine_3.result())
+SketchConstraintDistanceVertical_1 = Sketch_3.setVerticalDistance(SketchAPI_Arc(SketchArc_1).center(), SketchLine_2.startPoint(), 2)
+SketchConstraintDistanceVertical_2 = Sketch_3.setVerticalDistance(SketchAPI_Arc(SketchArc_1).center(), SketchLine_4.endPoint(), 2)
+ExtrusionCut_2.setNestedSketch(Sketch_3)
+model.do()
+# move only after the first extrusion-cut
+Part_1_doc.setCurrentFeature(ExtrusionCut_1.feature(), True)
+model.do()
+Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature(), True)
+model.end()
+assert(Part_1_doc.size("Groups") == 3) # 3 edges in groups results
+
+# check that simple move to the end provides 4 edges (no duplicates)
+model.undo()
+model.undo()
+
+model.begin()
+Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_2.feature(), True)
+model.end()
+assert(Part_1_doc.size("Groups") == 4) # 4 edges in groups results
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-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
+#
+
+# Check the movement to the end and split: whole results, check names of splitted results and groups
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-8.333743842364534, 20.52339901477833, -20.15024630541872, 20.52339901477833)
+SketchLine_2 = Sketch_1.addLine(-20.15024630541872, 20.52339901477833, -20.15024630541872, 3.980295566502462)
+SketchLine_3 = Sketch_1.addLine(-20.15024630541872, 3.980295566502462, -8.333743842364534, 3.980295566502462)
+SketchLine_4 = Sketch_1.addLine(-8.333743842364534, 3.980295566502462, -8.333743842364534, 20.52339901477833)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchCircle_1 = Sketch_1.addCircle(5.721674876847291, 12.81157635467982, 6.421166795138789)
+Extrusion_1.setNestedSketch(Sketch_1)
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")])
+Group_1.setName("GroupResult")
+Group_1.result().setName("GroupResult")
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_5 = Sketch_2.addLine(3.924377723198604, 15.23693857548147, -14.36967929032953, 15.23693857548147)
+SketchLine_6 = Sketch_2.addLine(-14.36967929032953, 15.23693857548147, -14.36967929032953, 11.61585476914922)
+SketchLine_7 = Sketch_2.addLine(-14.36967929032953, 11.61585476914922, 3.924377723198604, 11.61585476914922)
+SketchLine_8 = Sketch_2.addLine(3.924377723198604, 11.61585476914922, 3.924377723198604, 15.23693857548147)
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result())
+SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result())
+SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result())
+model.do()
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_2/Face-SketchLine_5r-SketchLine_6f-SketchLine_7f-SketchLine_8f_wire")], model.selection(), 2, 5)
+Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")], keepSubResults = True)
+model.do()
+Part_1_doc.moveFeature(Group_1.feature(), Fuse_1.feature(), True)
+model.end()
+
+assert(Part_1_doc.size("Groups") == 2) # 2 results because initially 2 results were selected
+
+# check names of results
+from ModelAPI import *
+res1 = modelAPI_Result(Part_1_doc.object("Groups", 0))
+assert(res1.data().name() == "GroupResult_1")
+res2 = modelAPI_Result(Part_1_doc.object("Groups", 1))
+assert(res2.data().name() == "GroupResult_2")
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-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
+#
+
+# Tests python API for the whole feature (all results) in group selection
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+Extrusion_1.setNestedSketch(Sketch_1)
+Group_1 = model.addGroup(Part_1_doc, "Vertices", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+Group_1.setName("CylVertices")
+Group_1.result().setName("CylVertices")
+Group_2 = model.addGroup(Part_1_doc, "Edges", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+Group_2.setName("CylEdges")
+Group_2.result().setName("CylEdges")
+Group_3 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+Group_3.setName("CylFaces")
+Group_3.result().setName("CylFaces")
+Group_4 = model.addGroup(Part_1_doc, "Solids", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+Group_4.setName("CylSolid")
+Group_4.result().setName("CylSolid")
+model.end()
+
+from GeomAPI import GeomAPI_ShapeIterator
+
+# group variable, type of selection, number of expected sub-shapes, sub-shapes type
+test_list = [(Group_1, "Vertices", 2, 7), (Group_2, "Edges", 3, 6), (Group_3, "Faces", 3, 4), (Group_4, "Solids", 1, 2)]
+for test in test_list:
+ assert(test[0].groupList().selectionType() == test[1])
+ assert(len(test[0].results()) == 1)
+ assert(test[0].result().shapeType() == "COMPOUND")
+
+ aResultShape = test[0].feature().firstResult().shape()
+ anIter = GeomAPI_ShapeIterator(aResultShape)
+ aNum = 0
+ while anIter.more():
+ aShape = anIter.current()
+ assert(aShape.shapeType() == test[3])
+ aNum = aNum + 1
+ anIter.next()
+
+ assert(aNum == test[2])
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2014-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
+#
+
+# Tests python API for the whole feature (all results) in group selection
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-12, 15, -12, -15)
+SketchLine_2 = Sketch_1.addLine(-12, -15, 12, 15)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(12, 15, 12, -15)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchLine_4 = Sketch_1.addLine(12, -15, -12, 15)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_4.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_4f"), model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, "Vertices", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+model.end()
+
+# check the group result: it must be compound of 12 vertices
+assert(Group_1.groupList().selectionType() == "Vertices")
+assert(len(Group_1.results()) == 1)
+assert(Group_1.result().shapeType() == "COMPOUND")
+
+from GeomAPI import GeomAPI_ShapeIterator
+aResultShape = Group_1.feature().firstResult().shape()
+anIter = GeomAPI_ShapeIterator(aResultShape)
+aNum = 0
+while anIter.more():
+ anEdge = anIter.current()
+ assert(anEdge.isVertex())
+ aNum = aNum + 1
+ anIter.next()
+
+assert(aNum == 12)
+
+assert(model.checkPythonDump())
tooltip="Create named collection of geometry entities"
icon="icons/Collection/shape_group.png"
apply_continue="true"
- helpfile="groupFeature.html">
+ helpfile="groupFeature.html"
+ hidefaces_panel="true">
<source path="group_widget.xml"/>
</feature>
myModal = false;
myIsTitleInToolbar = true;
myIsApplyContinue = false;
+ myHideFacesPanel = false;
+ myAbortConfirmation = true;
}
Config_FeatureMessage::~Config_FeatureMessage()
{
myIsTitleInToolbar = theValue;
}
+
+bool Config_FeatureMessage::isHideFacesPanel() const
+{
+ return myHideFacesPanel;
+}
+
+
+void Config_FeatureMessage::setHideFacesPanel(bool theValue)
+{
+ myHideFacesPanel = theValue;
+}
+
+bool Config_FeatureMessage::isAbortConfirmation() const
+{
+ return myAbortConfirmation;
+}
+
+void Config_FeatureMessage::setAbortConfirmation(bool theValue)
+{
+ myAbortConfirmation = theValue;
+}
bool myModal; ///<True if the feature has to be represented by modal dialog box
bool myIsAutoPreview; ///< Preview computation is performed automatically
bool myIsTitleInToolbar; ///< False if title should not be displayed in the toolbar
+ bool myHideFacesPanel; ///< Show or Hide HideFaces panel. By default is False
+ bool myAbortConfirmation; ///< Ask confirmation of abort of the feature from user
/// True if the feature can have Apply/Continue button in its property panel
bool myIsApplyContinue;
CONFIG_EXPORT bool isAutoPreview() const;
/// If true - title should normally be displayed in the toolbar
CONFIG_EXPORT bool isTitleInToolbar() const;
+ /// If true - then HideFaces panel has to be shown
+ CONFIG_EXPORT bool isHideFacesPanel() const;
+ CONFIG_EXPORT bool isAbortConfirmation() const;
///Set feature's Id
CONFIG_EXPORT void setId(const std::string& id);
CONFIG_EXPORT void setModal(bool isModal);
///Set flag to display title in toolbar
CONFIG_EXPORT void setTitleInToolbar(bool theValue);
+ ///Set flag to display title in toolbar
+ CONFIG_EXPORT void setHideFacesPanel(bool theValue);
+ ///Set flag to display title in toolbar
+ CONFIG_EXPORT void setAbortConfirmation(bool theValue);
///Set Apply/Continue state;
///If true - the feature can have Apply/Continue button in its property panel
CONFIG_EXPORT void setApplyContinue(bool isModal);
if (!aHelpFile.empty())
outFeatureMessage->setHelpFileName(myLibraryName + "/" + aHelpFile);
- if (isInternal) {
- //Internal feature has no visual representation.
- return;
- }
+ bool isHideFaces = getBooleanAttribute(theFeatureNode, HIDEFACES_PANEL, false);
+ outFeatureMessage->setHideFacesPanel(isHideFaces);
+
+ bool isConfirmAbort = getBooleanAttribute(theFeatureNode, ABORT_CONFIRMATION, true);
+ outFeatureMessage->setAbortConfirmation(isConfirmAbort);
+
+ //if (isInternal) {
+ // //Internal feature has no visual representation.
+ // return;
+ //}
std::string aText = Config_Translator::translate(anId, getProperty(theFeatureNode, FEATURE_TEXT));
outFeatureMessage->setText(aText);
// Widgets
const static char* WDG_INFO = "label";
+const static char* WDG_UNDOLABEL = "undo_label";
const static char* WDG_DOUBLEVALUE = "doublevalue";
const static char* WDG_DOUBLEVALUELABEL = "labelvalue";
const static char* WDG_INTEGERVALUE = "integervalue";
const static char* FEATURE_ICON = "icon";
const static char* FEATURE_TEXT = "title";
const static char* HELP_FILE = "helpfile";
+const static char* ABORT_CONFIRMATION = "abort_confirmation";
+const static char* HIDEFACES_PANEL = "hidefaces_panel";
const static char* FEATURE_KEYSEQUENCE = "keysequence";
const static char* FEATURE_NESTED = "nested";
const static char* FEATURE_WHEN_NESTED = "when_nested";
const static char* ATTR_ICON = FEATURE_ICON;
const static char* ATTR_LABEL = "label";
const static char* ATTR_STYLE_SHEET = "styleSheet";
+const static char* ATTR_HTML_STYLE = "isHTML";
const static char* ATTR_DEFAULT = "default";
const static char* ATTR_INTERNAL = "internal";
const static char* ATTR_OBLIGATORY = "obligatory";
const static char* ATTR_MODIFIED_IN_EDIT = "modified_in_edit";
const static char* ATTR_MAIN_ARG = "main_argument";
const static char* ATTR_GEOMETRICAL_SELECTION = "geometrical_selection";
+const static char* ATTR_VISUAL_CHANGED = "change_visual_attributes";
// WDG_INFO properties
*/
CONFIG_EXPORT bool getBooleanAttribute(const char* theAttributeName, bool theDefault) const;
- protected:
/// These fields are accessible for ModuleBase_WidgetFactory only
CONFIG_EXPORT Config_WidgetAPI(std::string theRawXml);
//! Pass to the next (sibling) node of widget's xml definition. If impossible, returns false
)
SET(TEXT_RESOURCES
-# ConnectorPlugin_msg_fr.ts
+ ConnectorPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+ <context>
+ <name>ExportToGEOM</name>
+ <message>
+ <source>Export all results and groups into GEOM module</source>
+ <translation>Exporter tous les résultats et groupes dans le module GEOM</translation>
+ </message>
+ <message>
+ <source>Export to GEOM</source>
+ <translation>Exporter vers GEOM</translation>
+ </message>
+ </context>
+</TS>
SET(TEXT_RESOURCES
ConstructionPlugin_msg_en.ts
+ ConstructionPlugin_msg_fr.ts
)
SET(PROJECT_LIBRARIES
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Construction</source>
+ <translation>Construction</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'axe par face fait référence à un type de forme non acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>L'axe par face ne peut être créé que sur une face</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>L'axe par face ne peut être créé que sur une face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>L'axe par face ne peut être créé que sur une face cylindrique</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>L'axe par une face ne peut pas être créé sur la face sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "FirstPoint" is not initialized.</source>
+ <translation>Sélectionnez le premier point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "SecondPoint" is not initialized.</source>
+ <translation>Sélectionnez le deuxième point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "CylindricalFace" is not initialized.</source>
+ <translation>Sélectionnez la face cylindrique</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Seule la sélection d'attribut peut être utilisée pour le premier point, pas %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le premier point fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>Uses composite construction feature without sub-features.</source>
+ <translation>Le premier point utilise une fonctionnalité de construction composite sans sous-fonctionnalités</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le premier point ne contient pas d'élément avec un type de forme acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le premier point ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le premier point fait référence à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Le premier point de type %1 n'est pas pris en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le premier point fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le premier point fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Le premier point fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Seule la sélection d'attribut peut être utilisée pour le deuxième point, pas %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le deuxième point fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>Uses composite construction feature without sub-features.</source>
+ <translation>Le deuxième point utilise une fonctionnalité de construction composite sans sous-fonctionnalités</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le deuxième point ne contient pas d'élément de type de forme acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le deuxième point ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPointGeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le deuxième point fait référence à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Le deuxième point de type %1 n'est pas pris en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le deuxième point fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le deuxième point fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Le deuxième point fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint:GeomValidators_DifferentShapes</name>
+ <message>
+ <source>The feature uses equal shapes.</source>
+ <translation>Les points d'axe doivent être différents</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:DZ</name>
+ <message>
+ <source>DZ </source>
+ <translation>DZ </translation>
+ </message>
+ <message>
+ <source>Z dimension</source>
+ <translation>Dimension Z</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint</name>
+ <message>
+ <source>First point</source>
+ <translation>Premier point</translation>
+ </message>
+ <message>
+ <source>Select a first point</source>
+ <translation>Sélectionnez un premier point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:SecondPoint</name>
+ <message>
+ <source>Second point</source>
+ <translation>Deuxième point</translation>
+ </message>
+ <message>
+ <source>Select a second point</source>
+ <translation>Sélectionnez un deuxième point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:line</name>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Select line.</source>
+ <translation>Sélectionnez une ligne.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:line:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:offset1</name>
+ <message>
+ <source>Distance </source>
+ <translation>Distance </translation>
+ </message>
+ <message>
+ <source>Distance value</source>
+ <translation>Distance</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:offset2</name>
+ <message>
+ <source>Distance </source>
+ <translation>Distance </translation>
+ </message>
+ <message>
+ <source>Distance value</source>
+ <translation>Distance</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane</name>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane1</name>
+ <message>
+ <source>1st plane</source>
+ <translation>1er plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane1:ConstructionPlugin_ValidatorAxisTwoNotParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane2</name>
+ <message>
+ <source>2nd plane</source>
+ <translation>2nd plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane2:ConstructionPlugin_ValidatorAxisTwoNotParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:point</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:reverse_offset1</name>
+ <message>
+ <source>Reverse</source>
+ <translation>Sens inverse</translation>
+ </message>
+ <message>
+ <source>Reverse offset value</source>
+ <translation>Valeur de décalage inverse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:reverse_offset2</name>
+ <message>
+ <source>Reverse</source>
+ <translation>Sens inverse</translation>
+ </message>
+ <message>
+ <source>Reverse offset value</source>
+ <translation>Valeur de décalage inverse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:use_offset1</name>
+ <message>
+ <source>Offset from 1st plane</source>
+ <translation>Décalage du 1er plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:use_offset2</name>
+ <message>
+ <source>Offset from 2nd plane</source>
+ <translation>Décalage du 2e plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Create axis</source>
+ <translation>Créer un axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace</name>
+ <message>
+ <source>Main object</source>
+ <translation>Objet principal</translation>
+ </message>
+ <message>
+ <source>Select a cylindrical object</source>
+ <translation>Sélectionnez un objet cylindrique</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:DX</name>
+ <message>
+ <source>DX </source>
+ <translation>DX </translation>
+ </message>
+ <message>
+ <source>X dimension</source>
+ <translation>Dimension X</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:DY</name>
+ <message>
+ <source>DY </source>
+ <translation>DY </translation>
+ </message>
+ <message>
+ <source>Y dimension</source>
+ <translation>Dimension Y</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CreationMethod</name>
+ <message>
+ <source>As axis of cylindrical face</source>
+ <translation>Comme axe de face cylindrique</translation>
+ </message>
+ <message>
+ <source>By line</source>
+ <translation>Par une ligne</translation>
+ </message>
+ <message>
+ <source>By plane and point</source>
+ <translation>Par un plan et un point</translation>
+ </message>
+ <message>
+ <source>By three dimensions</source>
+ <translation>Par trois dimensions</translation>
+ </message>
+ <message>
+ <source>By two planes</source>
+ <translation>Par deux plans</translation>
+ </message>
+ <message>
+ <source>By two points</source>
+ <translation>Par deux points</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:CylindricalFace</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un objet cylindrique.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:FirstPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un premier point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:line</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez une ligne.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un plan.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Axis:plane1</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un plan.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:planeFace:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Le plan fait référence à un type de forme non acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:planeFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>Le plan ne peut être créé que sur une face</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:planeFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>Le plan ne peut être créé que sur une face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:planeFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>Le plan ne peut être créé que sur une face cylindrique</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:planeFace:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>Le plan ne peut pas être créé sur la face sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "planeFace" is not initialized.</source>
+ <translation>Sélectionnez la face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "distance" is not initialized.</source>
+ <translation>Définir la distance</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane</name>
+ <message>
+ <source>Create plane</source>
+ <translation>Créer un plan</translation>
+ </message>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for rotation around axis.</source>
+ <translation>Angle de rotation autour de l'axe.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:axis</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select line for axis.</source>
+ <translation>Sélectionnez la ligne pour l'axe.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:axis:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:by_other_plane_option</name>
+ <message>
+ <source>By coincident to point</source>
+ <translation>Par coïncidence au point</translation>
+ </message>
+ <message>
+ <source>By distance from other</source>
+ <translation>Par distance aux autres</translation>
+ </message>
+ <message>
+ <source>By rotation</source>
+ <translation>Par rotation</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:coincident_point</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:creation_method</name>
+ <message>
+ <source>By line and point</source>
+ <translation>Par une ligne et un point</translation>
+ </message>
+ <message>
+ <source>By other plane</source>
+ <translation>Par un autre plan</translation>
+ </message>
+ <message>
+ <source>By three points</source>
+ <translation>Par trois points</translation>
+ </message>
+ <message>
+ <source>By two parallel planes</source>
+ <translation>Par deux plans parallèles</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:distance</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Distance from selected face to plane.</source>
+ <translation>Distance de la face sélectionnée au plan.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:line</name>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Select line.</source>
+ <translation>Sélectionnez une ligne.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:line:ConstructionPlugin_ValidatorPlaneLinePoint</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:perpendicular</name>
+ <message>
+ <source>Makes the plane perpendicular to the selected line.</source>
+ <translation>Rend le plan perpendiculaire à la ligne sélectionnée.</translation>
+ </message>
+ <message>
+ <source>Perpendicular </source>
+ <translation>Perpendiculaire </translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:plane</name>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:plane1</name>
+ <message>
+ <source>1st plane</source>
+ <translation>1er plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:plane1:ConstructionPlugin_ValidatorPlaneTwoParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:plane2</name>
+ <message>
+ <source>2nd plane</source>
+ <translation>2nd plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:plane2:ConstructionPlugin_ValidatorPlaneTwoParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point1</name>
+ <message>
+ <source>1st point</source>
+ <translation>1er point</translation>
+ </message>
+ <message>
+ <source>First point.</source>
+ <translation>Premier point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point1:ConstructionPlugin_ValidatorPlaneThreePoints</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point2</name>
+ <message>
+ <source>2nd point</source>
+ <translation>2ème point</translation>
+ </message>
+ <message>
+ <source>Second point.</source>
+ <translation>Deuxième point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point2:ConstructionPlugin_ValidatorPlaneThreePoints</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point3</name>
+ <message>
+ <source>3rd point</source>
+ <translation>3ème point</translation>
+ </message>
+ <message>
+ <source>Third point.</source>
+ <translation>Troisième point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point3:ConstructionPlugin_ValidatorPlaneThreePoints</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:point:ConstructionPlugin_ValidatorPlaneLinePoint</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Plane:reverse</name>
+ <message>
+ <source>Checked means on the other side of the selected plane.</source>
+ <translation>Coché signifie de l'autre côté du plan sélectionné.</translation>
+ </message>
+ <message>
+ <source>Reverse</source>
+ <translation>Sens inverse</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point</name>
+ <message>
+ <source>Create point</source>
+ <translation>Créer un point</translation>
+ </message>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:distance</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Distance value.</source>
+ <translation>Distance.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:edge</name>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <source>Edge for creating point on it.</source>
+ <translation>Arête où créer le point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:edge_for_point_projection</name>
+ <message>
+ <source>Edge for projection.</source>
+ <translation>Arête pour la projection.</translation>
+ </message>
+ <message>
+ <source>edge</source>
+ <translation>bord</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:face_for_point_projection</name>
+ <message>
+ <source>Face for projection.</source>
+ <translation>Face pour projection.</translation>
+ </message>
+ <message>
+ <source>face</source>
+ <translation>face</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line</name>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Line for intersection.</source>
+ <translation>Ligne d'intersection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line_1</name>
+ <message>
+ <source>First line</source>
+ <translation>Première ligne</translation>
+ </message>
+ <message>
+ <source>First line.</source>
+ <translation>Première ligne.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line_1:ConstructionPlugin_ValidatorPointLines</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line_2</name>
+ <message>
+ <source>Second line</source>
+ <translation>Deuxième ligne</translation>
+ </message>
+ <message>
+ <source>Second line.</source>
+ <translation>Deuxième ligne.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line_2:ConstructionPlugin_ValidatorPointLines</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane</name>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ <message>
+ <source>Plane for intersection.</source>
+ <translation>Plan d'intersection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_1</name>
+ <message>
+ <source>1st plane</source>
+ <translation>1er plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_2</name>
+ <message>
+ <source>2nd plane</source>
+ <translation>2nd plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_3</name>
+ <message>
+ <source>3rd plane</source>
+ <translation>3ème plan</translation>
+ </message>
+ <message>
+ <source>Select a planar face.</source>
+ <translation>Sélectionnez une face plane.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:object_for_center_of_circle</name>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Object for center of circle.</source>
+ <translation>Objet pour le centre du cercle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:object_for_center_of_gravity</name>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Object for center of gravity.</source>
+ <translation>Objet pour le centre de gravité.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:offset</name>
+ <message>
+ <source>Distance </source>
+ <translation>Distance </translation>
+ </message>
+ <message>
+ <source>Distance from the plane</source>
+ <translation>Distance du plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:point_to_project</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Point for projection.</source>
+ <translation>Point de projection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:ratio</name>
+ <message>
+ <source>Ratio</source>
+ <translation>Rapport</translation>
+ </message>
+ <message>
+ <source>Ratio value.</source>
+ <translation>Valeur du rapport.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:reverse</name>
+ <message>
+ <source>Distance from edge end point.</source>
+ <translation>Distance du point final du bord.</translation>
+ </message>
+ <message>
+ <source>Reverse</source>
+ <translation>Sens inverse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:reverse_offset</name>
+ <message>
+ <source>Reverse</source>
+ <translation>Sens inverse</translation>
+ </message>
+ <message>
+ <source>Reverse offset value</source>
+ <translation>Valeur de décalage inverse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:use_offset</name>
+ <message>
+ <source>Offset from the plane</source>
+ <translation>Décalage du plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "x" is not initialized.</source>
+ <translation>Sélectionnez la coordonnée x</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "y" is not initialized.</source>
+ <translation>Sélectionnez la coordonnée y</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "z" is not initialized.</source>
+ <translation>Sélectionnez la coordonnée z</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line:ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane:ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_1:ConstructionPlugin_ValidatorPointThreeNonParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_2:ConstructionPlugin_ValidatorPointThreeNonParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_3:ConstructionPlugin_ValidatorPointThreeNonParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:object_for_center_of_circle:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:creation_method</name>
+ <message>
+ <source>By X, Y, Z</source>
+ <translation>Par X, Y, Z</translation>
+ </message>
+ <message>
+ <source>By distance on edge</source>
+ <translation>Par distance au bord</translation>
+ </message>
+ <message>
+ <source>By geometrical property of object</source>
+ <translation>Par propriété géométrique d'objet</translation>
+ </message>
+ <message>
+ <source>By intersection of objects</source>
+ <translation>Par intersection d'objets</translation>
+ </message>
+ <message>
+ <source>By projection on edge or plane</source>
+ <translation>Par projection sur un bord ou un plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:geometrical_property_type</name>
+ <message>
+ <source>By center of circle</source>
+ <translation>Par centre de cercle</translation>
+ </message>
+ <message>
+ <source>By center of gravity</source>
+ <translation>Par centre de gravité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_line:ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane:ConstructionPlugin_ValidatorPointEdgeAndPlaneNotParallel</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_1:ConstructionPlugin_ValidatorPointThreeNonParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_2:ConstructionPlugin_ValidatorPointThreeNonParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_plane_3:ConstructionPlugin_ValidatorPointThreeNonParallelPlanes</name>
+ <message>
+ <source>One of the attribute is not initialized.</source>
+ <translation>Un des attributs n’est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:intersection_type</name>
+ <message>
+ <source>By line and plane intersection</source>
+ <translation>Par intersection d’une ligne et d'un plan</translation>
+ </message>
+ <message>
+ <source>By three planes intersection</source>
+ <translation>Par intersection de trois plans</translation>
+ </message>
+ <message>
+ <source>By two lines intersection</source>
+ <translation>Par intersection de deux lignes</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:offset_type</name>
+ <message>
+ <source>Distance on edge by ratio</source>
+ <translation>Distance au bord par ratio</translation>
+ </message>
+ <message>
+ <source>Distance on edge by value</source>
+ <translation>Distance au bord par valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>Point:projection_type</name>
+ <message>
+ <source>By projection on edge</source>
+ <translation>Par projection sur une arête</translation>
+ </message>
+ <message>
+ <source>By projection on face</source>
+ <translation>Par projection sur la face</translation>
+ </message>
+ </context>
+</TS>
title="Point"
tooltip="Create point"
icon="icons/Construction/point.png"
+ apply_continue="true"
helpfile="pointFeature.html">
<source path="point_widget.xml" />
</feature>
//
/* Events.i */
-%module EventsAPI
+%module(directors="1") EventsAPI
+%feature("director:except") {
+ if ($error != NULL) {
+ PyErr_Print();
+ std::cerr << std::endl;
+ throw Swig::DirectorMethodException();
+ }
+}
+
%{
#include "Events.h"
#include "Events_InfoMessage.h"
+ #include "Events_Listener.h"
+ #include "Events_Loop.h"
#include "Events_Message.h"
+ #include "Events_MessageGroup.h"
%}
%include "typemaps.i"
%include "std_string.i"
+// directors
+%feature("director") Events_Listener;
+
// all supported interfaces
%include "Events_Message.h"
%include "Events_InfoMessage.h"
+%include "Events_Listener.h"
+%include "Events_Loop.h"
+%include "Events_MessageGroup.h"
/// map from event ID to groupped messages (for flush for groupMessages=true listeners)
std::map<char*, std::shared_ptr<Events_Message> > myGroups;
- public:
+public:
+ virtual ~Events_Listener() {}
+
//! This method is called by loop when the event is started to process.
EVENTS_EXPORT virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage) = 0;
#include "ExchangeAPI_Export.h"
//--------------------------------------------------------------------------------------
+#include <ExchangePlugin_ExportPart.h>
+//--------------------------------------------------------------------------------------
#include <ModelAPI_Document.h>
#include <ModelAPI_Feature.h>
#include <ModelHighAPI_Tools.h>
return ExportPtr(new ExchangeAPI_Export(aFeature, theFilePath, theSelectedShape, "XAO"));
}
+void exportPart(const std::shared_ptr<ModelAPI_Document> & thePart,
+ const std::string & theFilePath,
+ const std::list<ModelHighAPI_Selection> & theSelected)
+{
+ FeaturePtr aFeature = thePart->addFeature(ExchangePlugin_ExportPart::ID());
+ aFeature->string(ExchangePlugin_ExportPart::FILE_PATH_ID())->setValue(theFilePath);
+ if (!theSelected.empty()) {
+ fillAttribute(theSelected,
+ aFeature->selectionList(ExchangePlugin_ExportPart::SELECTION_LIST_ID()));
+ }
+ // restart transaction to execute and delete the macro-feature
+ apply();
+}
//--------------------------------------------------------------------------------------
const std::string & theAuthor = std::string(),
const std::string & theGeometryName = std::string());
+
+/** \ingroup CPPHighAPI
+ * \brief Export selected features or the whole part to the binary file.
+ */
+EXCHANGEAPI_EXPORT void exportPart(
+ const std::shared_ptr<ModelAPI_Document> & thePart,
+ const std::string & theFilePath,
+ const std::list<ModelHighAPI_Selection> & theSelected = std::list<ModelHighAPI_Selection>());
+
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
#endif /* SRC_EXCHANGEAPI_EXCHANGEAPI_EXPORT_H_ */
#include "ExchangeAPI_Import.h"
//--------------------------------------------------------------------------------------
+#include <ExchangePlugin_ImportPart.h>
+//--------------------------------------------------------------------------------------
#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Services.h>
#include <ModelHighAPI_Tools.h>
//--------------------------------------------------------------------------------------
+#include <ModelAPI_AttributeStringArray.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+//--------------------------------------------------------------------------------------
#include <algorithm>
ExchangeAPI_Import::ExchangeAPI_Import(
std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(ExchangeAPI_Import::ID());
return ImportPtr(new ExchangeAPI_Import(aFeature, theFilePath));
}
+
+void importPart(const std::shared_ptr<ModelAPI_Document> & thePart,
+ const std::string & theFilePath,
+ const ModelHighAPI_Reference & theAfterThis)
+{
+ static const bool THE_VISIBLE_FEATURE = false;
+ FeaturePtr aCurrentFeature;
+ if (theAfterThis.feature()) {
+ aCurrentFeature = thePart->currentFeature(THE_VISIBLE_FEATURE);
+ thePart->setCurrentFeature(theAfterThis.feature(), THE_VISIBLE_FEATURE);
+ }
+
+ FeaturePtr aFeature = thePart->addFeature(ExchangePlugin_ImportPart::ID());
+ aFeature->string(ExchangePlugin_ImportPart::FILE_PATH_ID())->setValue(theFilePath);
+
+ // specify the ID of selected document
+ int aTargetPartIndex = 0;
+ SessionPtr aSession = ModelAPI_Session::get();
+ if (aSession->moduleDocument() == thePart) {
+ // Importing to PartSet has 2 choices: import directly to PartSet (if possible)
+ // or create a new part. Because then importing to existing part the document
+ // has to be specified explicitly.
+ // As a result, parse the list of possible target documents and generate new part
+ // if the import document is not applicable on PartSet level
+ // (there is no 'PartSet' in the list of applicable documents).
+ AttributeStringArrayPtr aDocsList =
+ aFeature->stringArray(ExchangePlugin_ImportPart::TARGET_PARTS_LIST_ID());
+ if (aDocsList->size() > 1 && aDocsList->value(1) == "PartSet")
+ aTargetPartIndex = 1;
+ }
+ aFeature->integer(ExchangePlugin_ImportPart::TARGET_PART_ID())->setValue(aTargetPartIndex);
+
+ // restart transaction to execute and delete the macro-feature
+ apply();
+
+ // restore current feature
+ if (aCurrentFeature)
+ thePart->setCurrentFeature(aCurrentFeature, THE_VISIBLE_FEATURE);
+}
#include <ModelHighAPI_Interface.h>
#include <ModelHighAPI_Macro.h>
+#include <ModelHighAPI_Reference.h>
+#include <ModelHighAPI_Selection.h>
//--------------------------------------------------------------------------------------
/**\class ExchangeAPI_Import
* \ingroup CPPHighAPI
ImportPtr addImport(const std::shared_ptr<ModelAPI_Document> & thePart,
const std::string & theFilePath);
+/** \ingroup CPPHighAPI
+ * \brief Import features from the file to the document after the current feature (or to the end).
+ */
+EXCHANGEAPI_EXPORT void importPart(
+ const std::shared_ptr<ModelAPI_Document> & thePart,
+ const std::string & theFilePath,
+ const ModelHighAPI_Reference & theAfterThis = ModelHighAPI_Reference());
+
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
#endif /* SRC_EXCHANGEAPI_EXCHANGEAPI_IMPORT_H_ */
${PROJECT_SOURCE_DIR}/src/ModelHighAPI
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
+ ${PROJECT_SOURCE_DIR}/src/GeomValidators
${PROJECT_SOURCE_DIR}/src/XAO
+ ${PROJECT_SOURCE_DIR}/src/ConstructionPlugin
+ ${PROJECT_SOURCE_DIR}/src/PartSetPlugin
)
SET(PROJECT_HEADERS
ExchangePlugin_Validators.h
ExchangePlugin_Tools.h
ExchangePlugin_Dump.h
+ ExchangePlugin_ImportPart.h
+ ExchangePlugin_ExportPart.h
)
SET(PROJECT_SOURCES
ExchangePlugin_Validators.cpp
ExchangePlugin_Tools.cpp
ExchangePlugin_Dump.cpp
+ ExchangePlugin_ImportPart.cpp
+ ExchangePlugin_ExportPart.cpp
)
SET(XML_RESOURCES
SET(TEXT_RESOURCES
ExchangePlugin_msg_en.ts
+ ExchangePlugin_msg_fr.ts
)
SET(PROJECT_LIBRARIES
ModelHighAPI
GeomAPI
GeomAlgoAPI
+ GeomValidators
XAOShaper
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Exchange)
INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
-ADD_UNIT_TESTS(TestImport.py
- TestExport.py
- Test2290.py
- Test2459.py
- TestExportToXAOWithFields.py
- TestExportToXAOWithGroupNotUpdated.py
- TestExport_FiniteValidator.py
+ADD_UNIT_TESTS(
+ TestImport.py
+ TestExport.py
+ Test2290.py
+ Test2459.py
+ TestExportToXAOWithFields.py
+ TestExportToXAOWithGroupNotUpdated.py
+ TestExport_FiniteValidator.py
+ TestExportPart_Failure_1.py
+ TestExportPart_Failure_2.py
+ TestExportPart_Failure_3.py
+ TestExportPart_FullPartSet.py
+ TestExportPart_FullPart_1.py
+ TestExportPart_FullPart_2.py
+ TestExportPart_PartSet.py
+ TestExportPart_Results_1.py
+ TestExportPart_Results_2.py
+ TestExportPart_Results_3.py
+ TestExportPart_Results_4.py
+ TestExportPart_Results_5.py
+ TestExportPart_Results_6.py
+ TestExportPart_Results_7.py
+ TestExportPart_Results_8.py
+ TestImportPart_AfterCurrent_1.py
+ TestImportPart_AfterCurrent_2.py
+ TestImportPart_AfterLast_1.py
+ TestImportPart_AfterLast_2.py
+ TestImportPart_AfterLast_3.py
+ TestImportPart_AfterLast_4.py
+ TestImportPart_AfterLast_5.py
+ TestImportPart_AfterLast_6.py
+ TestImportPart_Construction_1.py
+ TestImportPart_Construction_2.py
+ TestImportPart_Construction_3.py
+ TestImportPart_Construction_4.py
+ TestImportPart_Multiple.py
+ TestImportPart_ToEmptyPart.py
+ TestImportPart_ToEmptyPartSet.py
)
--- /dev/null
+// Copyright (C) 2014-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 <ExchangePlugin_ExportPart.h>
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <ConstructionPlugin_Axis.h>
+#include <ConstructionPlugin_Plane.h>
+#include <ConstructionPlugin_Point.h>
+
+#include <Events_InfoMessage.h>
+
+#include <PartSetPlugin_Part.h>
+
+#include <sstream>
+
+// Obtain all features to be exported to get the list of selected results.
+static void collectFeatures(DocumentPtr theDocument,
+ AttributeSelectionListPtr theSelected,
+ std::list<FeaturePtr>& theExport);
+// Obtain all constuction elements of the document.
+static void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport);
+// Check features could be exported. The following features cannot be exported:
+// * non-construction result (Part) when exporting the PartSet;
+// * features, which refer to objects from another document.
+// Returns true if all features can be exported.
+static bool verifyExport(const std::list<FeaturePtr>& theFeatures,
+ std::list<FeaturePtr>& theExternalReferences,
+ std::list<FeaturePtr>& theExportedParts);
+
+
+ExchangePlugin_ExportPart::ExchangePlugin_ExportPart()
+{
+}
+
+void ExchangePlugin_ExportPart::initAttributes()
+{
+ data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(FILE_FORMAT_ID(), ModelAPI_AttributeString::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FILE_FORMAT_ID());
+ data()->addAttribute(SELECTION_LIST_ID(), ModelAPI_AttributeSelectionList::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SELECTION_LIST_ID());
+}
+
+void ExchangePlugin_ExportPart::execute()
+{
+ AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
+ std::string aFilename = aFilePathAttr->value();
+ if (aFilename.empty()) {
+ setError("File name is empty.");
+ return;
+ }
+
+ std::list<FeaturePtr> aFeaturesToExport;
+
+ DocumentPtr anExportDoc = document();
+ DocumentPtr aPartSetDoc = ModelAPI_Session::get()->moduleDocument();
+ AttributeSelectionListPtr aSelected = selectionList(SELECTION_LIST_ID());
+ if (aSelected && aSelected->size() == 0 && anExportDoc == aPartSetDoc) {
+ // no result is selected, thus have to export all features of the current document,
+ // but the document is a PartSet; and it is forbidden to copy results of Parts,
+ // thus copy construction elements only
+ collectConstructions(anExportDoc, aFeaturesToExport);
+ }
+ else
+ collectFeatures(anExportDoc, aSelected, aFeaturesToExport);
+
+ if (aFeaturesToExport.empty()) {
+ Events_InfoMessage(getKind(), "Selected features cannot be exported from the document.").send();
+ return;
+ }
+
+ // remove 'ExportPart' feature if any
+ if (aFeaturesToExport.back()->getKind() == ExchangePlugin_ExportPart::ID())
+ aFeaturesToExport.pop_back();
+
+ std::list<FeaturePtr> anExternalLinks, aReferredParts;
+ if (!verifyExport(aFeaturesToExport, anExternalLinks, aReferredParts)) {
+ if (!anExternalLinks.empty()) {
+ // collect names of features as a string
+ std::ostringstream aListOfFeatures;
+ for (std::list<FeaturePtr>::iterator anIt = anExternalLinks.begin();
+ anIt != anExternalLinks.end(); ++anIt) {
+ if (anIt != anExternalLinks.begin())
+ aListOfFeatures << ", ";
+ aListOfFeatures << "'" << (*anIt)->name() << "'";
+ }
+
+ std::string aMessage = "The selected results were created using external references "
+ "outside of this Part from features %1. "
+ "Please, remove these references or select another "
+ "sub-set of results to be able to export.";
+ Events_InfoMessage(getKind(), aMessage).arg(aListOfFeatures.str()).send();
+ }
+ if (!aReferredParts.empty()) {
+ // collect names of parts as a string
+ std::ostringstream aListOfParts;
+ for (std::list<FeaturePtr>::iterator anIt = aReferredParts.begin();
+ anIt != aReferredParts.end(); ++anIt) {
+ if (anIt != aReferredParts.begin())
+ aListOfParts << ", ";
+ aListOfParts << "'" << (*anIt)->name() << "'";
+ }
+
+ std::string aMessage = "The selected results were created using references "
+ "to results of Parts %1. Please, remove these references "
+ "or select another sub-set of results to be able to export.";
+ Events_InfoMessage(getKind(), aMessage).arg(aListOfParts.str()).send();
+ }
+ // should not export anything
+ aFeaturesToExport.clear();
+ }
+
+ if (!aFeaturesToExport.empty()) {
+ // save the document
+ if (!anExportDoc->save(aFilename.c_str(), aFeaturesToExport))
+ setError("Cannot save the document.");
+ }
+}
+
+
+// ================================ Auxiliary functions ===================================
+
+static bool isCoordinate(FeaturePtr theFeature)
+{
+ return !theFeature->isInHistory() &&
+ (theFeature->getKind() == ConstructionPlugin_Point::ID() ||
+ theFeature->getKind() == ConstructionPlugin_Axis::ID() ||
+ theFeature->getKind() == ConstructionPlugin_Plane::ID());
+}
+
+static void allReferencedFeatures(const std::set<FeaturePtr>& theFeatures,
+ std::set<FeaturePtr>& theReferencedFeatures)
+{
+ std::set<FeaturePtr> aReferences;
+ for (std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin();
+ anIt != theFeatures.end(); ++anIt) {
+ theReferencedFeatures.insert(*anIt);
+
+ std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+ (*anIt)->data()->referencesToObjects(aRefs);
+
+ for (std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRIt = aRefs.begin();
+ aRIt != aRefs.end(); ++aRIt) {
+ for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
+ anObjIt != aRIt->second.end(); ++anObjIt) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
+ if (aFeature && !isCoordinate(aFeature) &&
+ theReferencedFeatures.find(aFeature) == theReferencedFeatures.end())
+ aReferences.insert(aFeature);
+ }
+ }
+ }
+
+ if (!aReferences.empty())
+ allReferencedFeatures(aReferences, theReferencedFeatures);
+}
+
+void collectFeatures(DocumentPtr theDocument,
+ AttributeSelectionListPtr theSelected,
+ std::list<FeaturePtr>& theExport)
+{
+ theExport = theDocument->allFeatures();
+
+ // remove all features after the current one
+ FeaturePtr aCurrentFeature = theDocument->currentFeature(false);
+ std::list<FeaturePtr>::iterator anIt = theExport.begin();
+ for (; anIt != theExport.end(); ++anIt)
+ if (*anIt == aCurrentFeature) {
+ theExport.erase(++anIt, theExport.end());
+ break;
+ }
+
+ if (!theSelected || theSelected->size() == 0) {
+ // nothing is selected, return all features of the document
+ return;
+ }
+
+ // collect initial list of features basing on the selected results
+ std::set<FeaturePtr> aFeaturesToExport;
+ for (int anIndex = 0, aSize = theSelected->size(); anIndex < aSize; ++anIndex) {
+ AttributeSelectionPtr aCurrent = theSelected->value(anIndex);
+ FeaturePtr aCurrentFeature = ModelAPI_Feature::feature(aCurrent->context());
+ if (aCurrentFeature)
+ aFeaturesToExport.insert(aCurrentFeature);
+ }
+ // recursively collect all features used for the selected results
+ allReferencedFeatures(aFeaturesToExport, aFeaturesToExport);
+
+ // remove the features which are not affect the selected results
+ anIt = theExport.begin();
+ while (anIt != theExport.end()) {
+ if (aFeaturesToExport.find(*anIt) == aFeaturesToExport.end()) {
+ std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
+ theExport.erase(aRemoveIt);
+ }
+ else
+ ++anIt;
+ }
+}
+
+void collectConstructions(DocumentPtr theDocument, std::list<FeaturePtr>& theExport)
+{
+ theExport = theDocument->allFeatures();
+ // keep constructions only
+ std::list<FeaturePtr>::iterator anIt = theExport.begin();
+ while (anIt != theExport.end()) {
+ FeaturePtr aCurFeature = *anIt;
+ ResultPtr aCurResult = aCurFeature->lastResult();
+
+ bool isApplicable =
+ (!aCurResult || aCurResult->groupName() == ModelAPI_ResultConstruction::group()) &&
+ !isCoordinate(aCurFeature);
+
+ if (isApplicable)
+ ++anIt;
+ else {
+ std::list<FeaturePtr>::iterator aRemoveIt = anIt++;
+ theExport.erase(aRemoveIt);
+ }
+ }
+}
+
+bool verifyExport(const std::list<FeaturePtr>& theFeatures,
+ std::list<FeaturePtr>& theExternalReferences,
+ std::list<FeaturePtr>& theExportedParts)
+{
+ for (std::list<FeaturePtr>::const_iterator anIt = theFeatures.begin();
+ anIt != theFeatures.end(); ++anIt) {
+ // full part should not be exported
+ if ((*anIt)->getKind() == PartSetPlugin_Part::ID())
+ theExportedParts.push_back(*anIt);
+
+ DocumentPtr aDoc = (*anIt)->document();
+
+ std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
+ (*anIt)->data()->referencesToObjects(aRefs);
+ std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRIt = aRefs.begin();
+ for (; aRIt != aRefs.end(); ++aRIt) {
+ for (std::list<ObjectPtr>::iterator anObjIt = aRIt->second.begin();
+ anObjIt != aRIt->second.end(); ++anObjIt) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
+ if (aFeature) {
+ // feature refers to external entity,
+ // which is neither the Origin nor coordinate axis or plane
+ if (aFeature->document() != aDoc && !isCoordinate(aFeature))
+ theExternalReferences.push_back(*anIt);
+ // feature refers to result of a part
+ if (aFeature->getKind() == PartSetPlugin_Part::ID())
+ theExportedParts.push_back(*anIt);
+ }
+ }
+ }
+ }
+
+ return theExternalReferences.empty() && theExportedParts.empty();
+}
--- /dev/null
+// Copyright (C) 2014-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 EXCHANGEPLUGIN_EXPORTPART_H_
+#define EXCHANGEPLUGIN_EXPORTPART_H_
+
+#include <ExchangePlugin.h>
+#include <ModelAPI_Feature.h>
+
+/**
+ * \class ExchangePlugin_ExportPart
+ * \ingroup Plugins
+ * \brief Feature for export some results of a Part to the binary format for the further import.
+ */
+class ExchangePlugin_ExportPart : public ModelAPI_Feature
+{
+public:
+ /// Feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_EXPORT_ID("ExportPart");
+ return MY_EXPORT_ID;
+ }
+ /// attribute name of file path
+ inline static const std::string& FILE_PATH_ID()
+ {
+ static const std::string MY_FILE_PATH_ID("file_path");
+ return MY_FILE_PATH_ID;
+ }
+ /// attribute name of file format
+ inline static const std::string& FILE_FORMAT_ID()
+ {
+ static const std::string MY_FILE_FORMAT_ID("file_format");
+ return MY_FILE_FORMAT_ID;
+ }
+ /// attribute name of selection list
+ inline static const std::string& SELECTION_LIST_ID()
+ {
+ static const std::string MY_SELECTION_LIST_ID("selection_list");
+ return MY_SELECTION_LIST_ID;
+ }
+ /// Default constructor
+ ExchangePlugin_ExportPart();
+
+ /// Returns the unique kind of a feature
+ EXCHANGEPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ return ExchangePlugin_ExportPart::ID();
+ }
+
+ /// Request for initialization of data model of the feature: adding all attributes
+ EXCHANGEPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Computes or recomputes the results
+ EXCHANGEPLUGIN_EXPORT virtual void execute();
+
+ /// Returns true if this feature is used as macro: creates other features and then removed.
+ EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+
+ /// Reimplemented from ModelAPI_Feature::isPreviewNeeded(). Returns false.
+ EXCHANGEPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; }
+
+ /// Do not put in history.
+ /// Since it is not a macro, it is not deleted, but we don't want to see it.
+ bool isInHistory() { return false; }
+};
+
+#endif /* EXCHANGEPLUGIN_EXPORTPART_H_ */
--- /dev/null
+// Copyright (C) 2014-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 <ExchangePlugin_ImportPart.h>
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeStringArray.h>
+#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
+
+#include <PartSetPlugin_Part.h>
+
+#include <map>
+#include <sstream>
+
+static const std::string THE_NEW_PART_STR("New Part");
+static const std::string THE_PART_SET_STR("PartSet");
+
+// Update names of imported features/results concurent with existing objects.
+static void correntNonUniqueNames(DocumentPtr theDocument, std::list<FeaturePtr>& theImported);
+// Find the document according to its name or create the new one.
+static DocumentPtr findDocument(DocumentPtr thePartSetDoc, const std::string& thePartName);
+
+ExchangePlugin_ImportPart::ExchangePlugin_ImportPart()
+{
+}
+
+void ExchangePlugin_ImportPart::initAttributes()
+{
+ data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(TARGET_PART_ID(), ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(TARGET_PARTS_LIST_ID(), ModelAPI_AttributeStringArray::typeId());
+}
+
+
+void ExchangePlugin_ImportPart::execute()
+{
+ AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
+ std::string aFilename = aFilePathAttr->value();
+ if (aFilename.empty()) {
+ setError("File name is empty.");
+ return;
+ }
+
+ // get the document where to import
+ AttributeStringArrayPtr aPartsAttr = stringArray(TARGET_PARTS_LIST_ID());
+ AttributeIntegerPtr aTargetAttr = integer(TARGET_PART_ID());
+ SessionPtr aSession = ModelAPI_Session::get();
+ DocumentPtr aDoc =
+ findDocument(aSession->moduleDocument(), aPartsAttr->value(aTargetAttr->value()));
+
+ // load the file into the document
+ std::list<FeaturePtr> anImportedFeatures;
+ if (aDoc && aDoc->importPart(aFilename.c_str(), anImportedFeatures))
+ correntNonUniqueNames(aDoc, anImportedFeatures);
+ else
+ setError("Cannot import the document.");
+}
+
+void ExchangePlugin_ImportPart::attributeChanged(const std::string& theID)
+{
+ if (theID == FILE_PATH_ID()) {
+ AttributeStringPtr aFilePathAttr = string(FILE_PATH_ID());
+ if (aFilePathAttr->value().empty())
+ return;
+
+ AttributeStringArrayPtr aPartsAttr = stringArray(TARGET_PARTS_LIST_ID());
+ AttributeIntegerPtr aTargetAttr = integer(TARGET_PART_ID());
+
+ // update the list of target parts
+ SessionPtr aSession = ModelAPI_Session::get();
+ DocumentPtr aDoc = document();
+ bool isPartSet = aDoc == aSession->moduleDocument();
+ if (isPartSet) {
+ std::list<std::string> anAcceptedValues;
+ anAcceptedValues.push_back(THE_NEW_PART_STR);
+
+ std::list<FeaturePtr> anImportedFeatures;
+ if (aDoc->importPart(aFilePathAttr->value().c_str(), anImportedFeatures, isPartSet))
+ anAcceptedValues.push_back(THE_PART_SET_STR);
+
+ // append names of all parts
+ std::list<FeaturePtr> aSubFeatures = aDoc->allFeatures();
+ for (std::list<FeaturePtr>::iterator aFIt = aSubFeatures.begin();
+ aFIt != aSubFeatures.end(); ++aFIt) {
+ if ((*aFIt)->getKind() == PartSetPlugin_Part::ID())
+ anAcceptedValues.push_back((*aFIt)->name());
+ }
+
+ if (aPartsAttr->size() != anAcceptedValues.size())
+ aTargetAttr->setValue(0);
+
+ aPartsAttr->setSize((int)anAcceptedValues.size());
+ std::list<std::string>::iterator anIt = anAcceptedValues.begin();
+ for (int anInd = 0; anIt != anAcceptedValues.end(); ++anIt, ++anInd)
+ aPartsAttr->setValue(anInd, *anIt);
+ }
+ else {
+ // keep only the name of the current part
+ if (aPartsAttr->size() == 0) {
+ FeaturePtr aPartFeature = ModelAPI_Tools::findPartFeature(aSession->moduleDocument(), aDoc);
+
+ aPartsAttr->setSize(1);
+ aPartsAttr->setValue(0, aPartFeature->name());
+ aTargetAttr->setValue(0);
+ }
+ }
+ }
+}
+
+
+// ================================ Auxiliary functions ===================================
+
+DocumentPtr findDocument(DocumentPtr thePartSetDoc, const std::string& thePartName)
+{
+ DocumentPtr aDoc;
+ if (thePartName == THE_PART_SET_STR)
+ aDoc = thePartSetDoc;
+ else {
+ FeaturePtr aPartFeature;
+ if (thePartName == THE_NEW_PART_STR) {
+ // create new part
+ aPartFeature = thePartSetDoc->addFeature(PartSetPlugin_Part::ID());
+ if (aPartFeature)
+ aPartFeature->execute();
+ }
+ else {
+ // find existing part by its name
+ std::list<FeaturePtr> aSubFeatures = thePartSetDoc->allFeatures();
+ for (std::list<FeaturePtr>::iterator aFIt = aSubFeatures.begin();
+ aFIt != aSubFeatures.end(); ++aFIt) {
+ if ((*aFIt)->getKind() == PartSetPlugin_Part::ID() && (*aFIt)->name() == thePartName) {
+ aPartFeature = *aFIt;
+ break;
+ }
+ }
+ }
+
+ if (aPartFeature) {
+ ResultPartPtr aPartResult =
+ std::dynamic_pointer_cast<ModelAPI_ResultPart>(aPartFeature->lastResult());
+ if (aPartResult)
+ aDoc = aPartResult->partDoc();
+ }
+ }
+ return aDoc;
+}
+
+typedef std::map<std::string, std::map<std::string, std::set<int> > > ObjectNameMap;
+
+bool splitName(std::string& theName, int& theIndex)
+{
+ size_t aLastUndercore = theName.find_last_of('_');
+ bool isOk = aLastUndercore != std::string::npos;
+ if (isOk) {
+ char* isNumber;
+ std::string anIndexStr = theName.substr(aLastUndercore + 1);
+ theIndex = std::strtol(anIndexStr.c_str(), &isNumber, 10);
+ isOk = isNumber != 0;
+ if (isOk)
+ theName.erase(aLastUndercore);
+ }
+ return isOk;
+}
+
+void addIndexedName(const ObjectPtr& theObject, ObjectNameMap& theIndexedNames)
+{
+ std::string aName = theObject->data()->name();
+ std::string aGroup = theObject->groupName();
+ int anIndex = 0;
+ bool isIndexed = splitName(aName, anIndex);
+ std::set<int>& anIndices = theIndexedNames[aGroup][aName];
+ if (isIndexed)
+ anIndices.insert(anIndex);
+}
+
+// Collect names of features and results in the document before the import.
+// The name of indexed feature/result will be split to the name and the index. For example ,
+// 'Point_1', 'Point_2' will be placed at the same key with the set of corrsponding indices:
+// 'Point_1', 'Point_2' => {'Point', [1, 2]}.
+// Thus, the new point should have index 3 and therefore the name 'Point_3'.
+static void collectOldNames(DocumentPtr theDocument, std::list<FeaturePtr>& theAvoided,
+ ObjectNameMap& theIndexedNames)
+{
+ std::list<FeaturePtr> anAllFeatures = theDocument->allFeatures();
+ std::list<FeaturePtr>::iterator aFIt = anAllFeatures.begin();
+ std::list<FeaturePtr>::iterator anAvoidIt = theAvoided.begin();
+ for (; aFIt != anAllFeatures.end(); ++aFIt) {
+ if (anAvoidIt != theAvoided.end() && *aFIt == *anAvoidIt) {
+ // skip this feature
+ ++anAvoidIt;
+ continue;
+ }
+
+ // store name of feature
+ addIndexedName(*aFIt, theIndexedNames);
+ // store names of results
+ const std::list<ResultPtr>& aResults = (*aFIt)->results();
+ for (std::list<ResultPtr>::const_iterator aRIt = aResults.begin();
+ aRIt != aResults.end(); ++aRIt)
+ addIndexedName(*aRIt, theIndexedNames);
+ }
+}
+
+static std::string uniqueName(const ObjectPtr& theObject, ObjectNameMap& theExistingNames)
+{
+ std::string aName = theObject->data()->name();
+ std::string aGroup = theObject->groupName();
+ int anIndex = 1;
+ splitName(aName, anIndex);
+
+ ObjectNameMap::iterator aFoundGroup = theExistingNames.find(aGroup);
+ bool isUnique = aFoundGroup == theExistingNames.end();
+
+ std::map<std::string, std::set<int> >::iterator aFound;
+ if (!isUnique) {
+ aFound = aFoundGroup->second.find(aName);
+ isUnique = aFound == aFoundGroup->second.end();
+ }
+
+ if (isUnique) {
+ // name is unique
+ aName = theObject->data()->name();
+ addIndexedName(theObject, theExistingNames);
+ }
+ else {
+ // search the appropriate index
+ std::set<int>::iterator aFoundIndex = aFound->second.find(anIndex);
+ for (; aFoundIndex != aFound->second.end(); ++aFoundIndex, ++anIndex)
+ if (anIndex != *aFoundIndex)
+ break;
+ // compose the new name
+ std::ostringstream aNewName;
+ aNewName << aName << "_" << anIndex;
+ aName = aNewName.str();
+ // add new index
+ aFound->second.insert(anIndex);
+ }
+
+ return aName;
+}
+
+void correntNonUniqueNames(DocumentPtr theDocument, std::list<FeaturePtr>& theImported)
+{
+ ObjectNameMap aNames;
+ collectOldNames(theDocument, theImported, aNames);
+
+ for (std::list<FeaturePtr>::iterator anIt = theImported.begin();
+ anIt != theImported.end(); ++anIt) {
+ // update name of feature
+ std::string aNewName = uniqueName(*anIt, aNames);
+ (*anIt)->data()->setName(aNewName);
+ // update names of results
+ const std::list<ResultPtr>& aResults = (*anIt)->results();
+ for (std::list<ResultPtr>::const_iterator aRIt = aResults.begin();
+ aRIt != aResults.end(); ++aRIt) {
+ aNewName = uniqueName(*aRIt, aNames);
+ (*aRIt)->data()->setName(aNewName);
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2014-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 EXCHANGEPLUGIN_IMPORTPART_H_
+#define EXCHANGEPLUGIN_IMPORTPART_H_
+
+#include <ExchangePlugin.h>
+#include <ModelAPI_Feature.h>
+
+/**
+ * \class ExchangePlugin_ImportPart
+ * \ingroup Plugins
+ * \brief Feature for import the structure of Part into the current document.
+ */
+class ExchangePlugin_ImportPart : public ModelAPI_Feature
+{
+public:
+ /// Feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_IMPORT_ID("ImportPart");
+ return MY_IMPORT_ID;
+ }
+ /// attribute name of file path
+ inline static const std::string& FILE_PATH_ID()
+ {
+ static const std::string MY_FILE_PATH_ID("file_path");
+ return MY_FILE_PATH_ID;
+ }
+ /// attribute name of target part
+ inline static const std::string& TARGET_PART_ID()
+ {
+ static const std::string MY_TARGET_PART_ID("target_part");
+ return MY_TARGET_PART_ID;
+ }
+ /// attribute name of list of target parts
+ inline static const std::string& TARGET_PARTS_LIST_ID()
+ {
+ static const std::string MY_TARGET_PARTS_LIST_ID("target_parts_list");
+ return MY_TARGET_PARTS_LIST_ID;
+ }
+ /// Default constructor
+ ExchangePlugin_ImportPart();
+
+ /// Returns the unique kind of a feature
+ EXCHANGEPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ return ExchangePlugin_ImportPart::ID();
+ }
+
+ /// Request for initialization of data model of the feature: adding all attributes
+ EXCHANGEPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object
+ /// \param theID identifier of changed attribute
+ EXCHANGEPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Computes or recomputes the results
+ EXCHANGEPLUGIN_EXPORT virtual void execute();
+
+ /// Returns true if this feature is used as macro: creates other features and then removed.
+ EXCHANGEPLUGIN_EXPORT virtual bool isMacro() const { return true; }
+
+ /// Reimplemented from ModelAPI_Feature::isPreviewNeeded(). Returns false.
+ EXCHANGEPLUGIN_EXPORT virtual bool isPreviewNeeded() const { return false; }
+};
+
+#endif /* EXCHANGEPLUGIN_IMPORTPART_H_ */
#include <ExchangePlugin_Dump.h>
#include <ExchangePlugin_ImportFeature.h>
#include <ExchangePlugin_ExportFeature.h>
+#include <ExchangePlugin_ImportPart.h>
+#include <ExchangePlugin_ExportPart.h>
#include <ExchangePlugin_Validators.h>
#include <Config_PropManager.h>
new ExchangePlugin_ImportFormatValidator);
aFactory->registerValidator("ExchangePlugin_ExportFormat",
new ExchangePlugin_ExportFormatValidator);
+ aFactory->registerValidator("ExchangePlugin_InHistory",
+ new ExchangePlugin_InHistoryValidator);
}
FeaturePtr ExchangePlugin_Plugin::createFeature(std::string theFeatureID)
if (theFeatureID == ExchangePlugin_ExportFeature::ID()) {
return FeaturePtr(new ExchangePlugin_ExportFeature);
} else
+ if (theFeatureID == ExchangePlugin_ImportPart::ID()) {
+ return FeaturePtr(new ExchangePlugin_ImportPart);
+ } else
+ if (theFeatureID == ExchangePlugin_ExportPart::ID()) {
+ return FeaturePtr(new ExchangePlugin_ExportPart);
+ } else
if (theFeatureID == ExchangePlugin_Dump::ID()) {
return FeaturePtr(new ExchangePlugin_Dump);
}
#include <ModelAPI_Object.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
#include <list>
#include <string>
theError = "File name does not end with any available format.";
return false;
}
+
+
+bool ExchangePlugin_InHistoryValidator::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ std::string anAttributeType = theAttribute->attributeType();
+ if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
+ AttributeSelectionPtr anAttrSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+ ResultPtr aContext = anAttrSelection->context();
+ if (!aContext.get()) {
+ theError = "Error: Context is empty.";
+ return false;
+ }
+
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aContext);
+ if (!aFeature->isInHistory()) {
+ theError = "Error: Feature is not in history.";
+ return false;
+ }
+ } else if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
+ AttributeSelectionListPtr anAttrSelectionList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+
+ // All objects should not be result constructions.
+ for(int anIndex = 0, aSize = anAttrSelectionList->size(); anIndex < aSize; ++anIndex) {
+ AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+ if(!isValid(anAttrSelection, theArguments, theError)) {
+ return false;
+ }
+ }
+ } else {
+// LCOV_EXCL_START
+ theError = "Error: Attribute \"%1\" does not supported by this validator.";
+ theError.arg(anAttributeType);
+ return false;
+// LCOV_EXCL_STOP
+ }
+
+ return true;
+}
};
+/**
+ * Check the selected result is in history (avoid Origin and coordinate axes and planes).
+ */
+class ExchangePlugin_InHistoryValidator : public ModelAPI_AttributeValidator
+{
+public:
+ /// \return True if the attribute is valid.
+ /// It checks whether the selected object is in history.
+ /// \param[in] theAttribute an attribute to check
+ /// \param[in] theArguments a filter parameters
+ /// \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
#endif
<translation>Attribute %1 is not a string.</translation>
</message>
</context>
+
+ <context>
+ <name>Export:ExchangePlugin_ExportPart</name>
+ <message>
+ <source>Cannot save the document.</source>
+ <translation>Cannot save the document.</translation>
+ </message>
+ <message>
+ <source>Selected features cannot be exported from the document.</source>
+ <translation>Selected features cannot be exported from the document.</translation>
+ </message>
+ <message>
+ <source>The selected results were created using external references outside of this Part from features %1. Please, remove these references or select another sub-set of results to be able to export.</source>
+ <translation>The selected results were created using external references outside of this Part from features %1. Please, remove these references or select another sub-set of results to be able to export.</translation>
+ </message>
+ <message>
+ <source>The selected results were created using references to results of Parts %1. Please, remove these references or select another sub-set of results to be able to export.</source>
+ <translation>The selected results were created using references to results of Parts %1. Please, remove these references or select another sub-set of results to be able to export.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Import:ExchangePlugin_ImportPart</name>
+ <message>
+ <source>Cannot import the document.</source>
+ <translation>Cannot import the document.</translation>
+ </message>
+ </context>
</TS>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Dump</source>
+ <translation>Déverser</translation>
+ </message>
+ <message>
+ <source>Export</source>
+ <translation>Export</translation>
+ </message>
+ <message>
+ <source>Import</source>
+ <translation>Import</translation>
+ </message>
+ </context>
+
+ <!-- Dump -->
+ <context>
+ <name>Dump</name>
+ <message>
+ <source>Dump</source>
+ <translation>Déverser</translation>
+ </message>
+ <message>
+ <source>Dump Python script</source>
+ <translation>Déverser dans un script Python</translation>
+ </message>
+ </context>
+ <context>
+ <name>Dump:file_format</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Dump:file_path</name>
+ <message>
+ <source>Dump to file</source>
+ <translation>Déverser dans un fichier</translation>
+ </message>
+ </context>
+ <context>
+ <name>Dump:file_path:ExchangePlugin_ExportFormat</name>
+ <message>
+ <source>File name is empty.</source>
+ <translation>Le nom du fichier est vide.</translation>
+ </message>
+ </context>
+
+ <!-- Export -->
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "file_format" is not initialized.</source>
+ <translation>Le nom du fichier d'export n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "selection_list" is not initialized.</source>
+ <translation>Les objets à exporter ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:file_path:ExchangePlugin_ExportFormat</name>
+ <message>
+ <source>File name is empty.</source>
+ <translation>Le nom du fichier d'export n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:selection_list:GeomValidators_Finite</name>
+ <message>
+ <source>Infinite result is selected.</source>
+ <translation>Seules les formes finies peuvent être exportées</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "file_path" is not initialized.</source>
+ <translation>Définir le chemin du fichier exporté</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "selection_list" is not initialized.</source>
+ <translation>Les objets à exporter ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "xao_file_path" is not initialized.</source>
+ <translation>Définir le chemin du fichier XAO exporté</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "xao_author" is not initialized.</source>
+ <translation>Définir l'auteur du fichier XAO</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "xao_geometry_name" is not initialized.</source>
+ <translation>Définir le nom de la géométrie du fichier XAO</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:ExchangePlugin_ExportFormat</name>
+ <message>
+ <source>%1 is not initialized.</source>
+ <translation>L'attribut %1 n'est pas initialisé.</translation>
+ </message>
+ <message>
+ <source>%1 is not a string attribute.</source>
+ <translation>L'attribut %1 n'est pas une chaîne.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export</name>
+ <message>
+ <source>Export</source>
+ <translation>Export</translation>
+ </message>
+ <message>
+ <source>Export to file</source>
+ <translation>Exporter dans un fichier</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:ExportType</name>
+ <message>
+ <source>BREP, STEP, IGES</source>
+ <translation>BREP, STEP, IGES</translation>
+ </message>
+ <message>
+ <source>XAO</source>
+ <translation>XAO</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:file_path</name>
+ <message>
+ <source>Export file</source>
+ <translation>Fichier d'export</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:selection_list</name>
+ <message>
+ <source>Select a set of objects</source>
+ <translation>Sélectionnez un ensemble d'objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:xao_author</name>
+ <message>
+ <source>Author</source>
+ <translation>Auteur</translation>
+ </message>
+ <message>
+ <source>Please input the author</source>
+ <translation>S'il vous plaît saisissez l'auteur</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:xao_file_path</name>
+ <message>
+ <source>Export file</source>
+ <translation>Fichier d'export</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:xao_file_path:ExchangePlugin_ExportFormat</name>
+ <message>
+ <source>%1 is not initialized.</source>
+ <translation>%1 n'est pas initialisé.</translation>
+ </message>
+ <message>
+ <source>File name is empty.</source>
+ <translation>Le nom du fichier est vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Export:xao_geometry_name</name>
+ <message>
+ <source>Geometry name</source>
+ <translation>Nom de la géométrie</translation>
+ </message>
+ <message>
+ <source>Please input the geometry name</source>
+ <translation>S'il vous plaît entrer le nom de la géométrie</translation>
+ </message>
+ </context>
+
+ <!-- Import -->
+ <context>
+ <name>Import:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "file_path" is not initialized.</source>
+ <translation>Nom du fichier d'entrée à importer</translation>
+ </message>
+ </context>
+ <context>
+ <name>Import:file_path:ExchangePlugin_ImportFormat</name>
+ <message>
+ <source>File name is empty.</source>
+ <translation>Nom du fichier d'entrée à importer</translation>
+ </message>
+ </context>
+ <context>
+ <name>Import</name>
+ <message>
+ <source>Import</source>
+ <translation>Import</translation>
+ </message>
+ <message>
+ <source>Import a file</source>
+ <translation>Importer un fichier</translation>
+ </message>
+ </context>
+ <context>
+ <name>Import:file_path</name>
+ <message>
+ <source>Import file</source>
+ <translation>Importer le fichier</translation>
+ </message>
+ </context>
+
+</TS>
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+model.begin()
+model.exportPart(partSet, filename, [Part_1.result()])
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting result of Part_1 should fail"
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Box_1
+
+model.begin()
+model.exportPart(Part_1_doc, filename, [featureToExport.result()])
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting of {} from document {} should fail".format(featureToExport.name(), Part_1.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+model.do()
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Part_1/[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"))
+Translation_1 = model.addTranslation(partSet, [model.selection("COMPOUND", "Part_1/")], model.selection("EDGE", "Axis_4"), 10)
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+model.begin()
+model.exportPart(partSet, filename)
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting of PartSet should fail"
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+model.begin()
+model.exportPart(partSet, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Failed to export full PartSet"
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting of Part_1 should fail"
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+model.begin()
+model.exportPart(Part_2_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export Part_2 to file {}".format(filename)
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+model.begin()
+model.exportPart(partSet, filename, [Axis_4.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export construction elements of PartSet"
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Point_2
+
+model.begin()
+model.exportPart(partSet, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Axis_4
+
+model.begin()
+model.exportPart(partSet, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Sketch_1
+
+model.begin()
+model.exportPart(Part_1_doc, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Extrusion_1
+
+model.begin()
+model.exportPart(Part_1_doc, filename, [featureToExport.result()])
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting of {} should fail".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Sketch_2
+
+model.begin()
+model.exportPart(Part_1_doc, filename, [featureToExport.result()])
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting of {} should fail".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Revolution_1
+
+model.begin()
+model.exportPart(Part_1_doc, filename, [featureToExport.result()])
+model.end()
+assert not os.path.exists(filename), "ERROR: Exporting of {} should fail".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Box_1
+
+model.begin()
+model.exportPart(Part_2_doc, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+import os
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Translation_1
+
+model.begin()
+model.exportPart(Part_2_doc, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), model.selection("EDGE", "PartSet/OY"), 45)
+model.do()
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# store the reference data
+features = Part_1_doc.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export all features from Part_1
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export features from {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+model.end()
+
+# store features before the import
+featuresBeforeImportBegin = Part_1_doc.allFeatures()
+featuresBeforeImportBegin.pop_back() # remove Translation_1
+featuresBeforeImportBegin.pop_back() # remove Extrusion_1
+featuresBeforeImportFinish = [Translation_1.feature(), Extrusion_1.feature()]
+
+# import the document after Sketch_1
+model.begin()
+model.importPart(Part_1_doc, filename, Sketch_1)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImportBegin:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+for feat in featuresBeforeImportFinish:
+ if features.back().getKind() == feat.getKind() and features.back().name() == feat.name():
+ features.pop_back()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), model.selection("EDGE", "PartSet/OY"), 45)
+model.do()
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# store the reference data
+features = Part_1_doc.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export all features from Part_1
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export features from {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+model.end()
+
+# store features before the import
+featuresBeforeImportBegin = Part_1_doc.allFeatures()
+featuresBeforeImportBegin.pop_back() # remove Translation_1
+featuresBeforeImportFinish = [Translation_1.feature()]
+
+# import the document after Extrusion_1
+model.begin()
+model.importPart(Part_1_doc, filename, Extrusion_1)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImportBegin:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+for feat in featuresBeforeImportFinish:
+ if features.back().getKind() == feat.getKind() and features.back().name() == feat.name():
+ features.pop_back()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# store the reference data
+features = [Point_2.feature(), Axis_4.feature()]
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export feature from PartSet
+featureToExport = Axis_4
+model.begin()
+model.exportPart(partSet, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+model.end()
+
+# store features before the import
+featuresBeforeImport = Part_1_doc.allFeatures()
+
+# import the document
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImport:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Sketch_1
+
+# store the reference data
+sketch = featureToCompositeFeature(featureToExport.feature())
+features = [sketch]
+for i in range(0, sketch.numberOfSubs()):
+ features.append(sketch.subFeature(i))
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export sketch from Part_1
+model.begin()
+model.exportPart(Part_1_doc, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+model.end()
+
+# store features before the import
+featuresBeforeImport = Part_1_doc.allFeatures()
+
+# import the document
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImport:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Box_1
+
+# store the reference data
+features = [featureToExport.feature()]
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export feature from Part_2
+model.begin()
+model.exportPart(Part_2_doc, filename, [featureToExport.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+model.end()
+
+# store features before the import
+featuresBeforeImport = Part_1_doc.allFeatures()
+
+# import the document
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImport:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+model.do()
+
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+featureToExport = Translation_1
+
+# store the reference data
+features = [Box_1.feature(), Translation_1.feature()]
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export all features from Part_2
+model.begin()
+model.exportPart(Part_2_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export feature {}".format(featureToExport.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+model.end()
+
+# store features before the import
+featuresBeforeImport = Part_1_doc.allFeatures()
+
+# import the document
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImport:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+Plane_4 = model.addPlane(Part_2_doc, model.selection("FACE", "PartSet/YOZ"), model.selection("EDGE", "PartSet/OY"), 45)
+model.do()
+
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# store the reference data
+features = [Box_1.feature(), Plane_4.feature()]
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export specified features from Part_2
+model.begin()
+model.exportPart(Part_2_doc, filename, [Box_1.result(), Plane_4.result()])
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export features {} and {}".format(feature[0].name(), features[1].name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+model.end()
+
+# store features before the import
+featuresBeforeImport = Part_1_doc.allFeatures()
+
+# import the document
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImport:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Point_2 = model.addPoint(partSet, 100, 100, 100)
+Axis_4 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "PartSet/Axis_4"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+
+Part_2 = model.addPart(partSet)
+Part_2_doc = Part_2.document()
+Box_1 = model.addBox(Part_2_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_2_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+Plane_4 = model.addPlane(Part_2_doc, model.selection("FACE", "PartSet/YOZ"), model.selection("EDGE", "PartSet/OY"), 45)
+model.do()
+
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# store the reference data
+features = [Box_1.feature(), Translation_1.feature()]
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+# export all features before the history line from Part_2
+model.begin()
+Part_2_doc.setCurrentFeature(Translation_1.feature(), False)
+model.exportPart(Part_2_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export features {} and {}".format(feature[0].name(), features[1].name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+model.end()
+
+# store features before the import
+featuresBeforeImport = Part_1_doc.allFeatures()
+
+# import the document
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+for feat in featuresBeforeImport:
+ if features.front().getKind() == feat.getKind() and features.front().name() == feat.name():
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+# PartSet => PartSet
+
+model.begin()
+partSet = model.moduleDocument()
+Point_1 = model.addPoint(partSet, 100, 100, 100)
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Axis_1 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+model.end()
+
+# store the reference data
+features = partSet.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# emport the document
+model.begin()
+model.exportPart(partSet, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export PartSet"
+
+# close all documents
+model.reset()
+
+# import the document
+model.begin()
+partSet = model.moduleDocument()
+model.importPart(partSet, filename)
+model.end()
+
+# Test 1. No Part should be created
+assert(partSet.size(ModelAPI_ResultPart.group()) == 0)
+
+# Test 2. Compare results with the reference data
+TOLERANCE = 1.e-7
+features = partSet.allFeatures()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+# PartSet => Part
+
+model.begin()
+partSet = model.moduleDocument()
+Point_1 = model.addPoint(partSet, 100, 100, 100)
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Axis_1 = model.addAxis(partSet, model.selection("VERTEX", "Origin"), model.selection("VERTEX", "Point_2"))
+model.end()
+
+# store the reference data (without Origin, coordinate axes and planes)
+features = partSet.allFeatures()
+for i in range(0, 7):
+ features.pop_front()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# emport the document
+model.begin()
+model.exportPart(partSet, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export PartSet"
+
+# close all documents
+model.reset()
+
+# import the document
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# Test 1. No Part should be created
+assert(partSet.size(ModelAPI_ResultPart.group()) == 1)
+
+# Test 2. Compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+# Part => PartSet
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Point_1 = model.addPoint(Part_1_doc, 100, 100, 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Axis_1 = model.addAxis(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("VERTEX", "Point_1"))
+model.end()
+
+# store the reference data
+features = Part_1_doc.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# emport the document
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# import the document
+model.begin()
+partSet = model.moduleDocument()
+model.importPart(partSet, filename)
+model.end()
+
+# Test 1. No new Part should be created
+assert(partSet.size(ModelAPI_ResultPart.group()) == 0)
+
+# Test 2. Compare results with the reference data
+TOLERANCE = 1.e-7
+features = partSet.allFeatures()
+for i in range(0, 7):
+ # exclude Origin, coordinate axes and planes
+ features.pop_front()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+# Part => Part
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Point_1 = model.addPoint(Part_1_doc, 100, 100, 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Axis_1 = model.addAxis(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("VERTEX", "Point_1"))
+model.end()
+
+# store the reference data
+features = Part_1_doc.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# emport the document
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# import the document
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# Test 1. No new Part should be created
+assert(partSet.size(ModelAPI_ResultPart.group()) == 1)
+
+# Test 2. Compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), 100)
+Translation_1.setName("MovedBox")
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/YOZ"), model.selection("EDGE", "PartSet/OY"), 45)
+model.do()
+model.end()
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# export all features from Part_1
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export features from {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# create new Part
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(-20, -40, -50, -40)
+SketchLine_2 = Sketch_1.addLine(-50, -40, -50, -10)
+SketchLine_3 = Sketch_1.addLine(-50, -10, -20, -10)
+SketchLine_4 = Sketch_1.addLine(-20, -10, -20, -40)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 20)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_3.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 30, 0)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OX"), 50)
+model.end()
+
+
+def checkUniqueNames(theDocument):
+ features = theDocument.allObjects()
+ names = set()
+ for feat in features:
+ name = feat.data().name()
+ if not name == "":
+ assert(not name in names), "'{}' already exists in {}".format(name, names)
+ names.add(name)
+
+
+# import the document at the end
+model.begin()
+model.importPart(Part_1_doc, filename)
+model.end()
+checkUniqueNames(Part_1_doc)
+
+# import the document after Extrusion_1
+model.begin()
+model.importPart(Part_1_doc, filename, Extrusion_1)
+model.end()
+checkUniqueNames(Part_1_doc)
+
+# import the document after Sketch_1
+model.begin()
+model.importPart(Part_1_doc, filename, Sketch_1)
+model.end()
+checkUniqueNames(Part_1_doc)
+
+# import the document after Translation_1
+model.begin()
+model.importPart(Part_1_doc, filename, Translation_1)
+model.end()
+checkUniqueNames(Part_1_doc)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Point_1 = model.addPoint(Part_1_doc, 100, 100, 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Axis_1 = model.addAxis(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("VERTEX", "Point_1"))
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "Axis_1"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+model.end()
+
+# store the reference data
+features = Part_1_doc.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# emport the document
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# import the document
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.importPart(Part_1_doc, filename)
+model.end()
+
+# Test 1. No new Part should be created
+assert(partSet.size(ModelAPI_ResultPart.group()) == 1)
+
+# Test 2. Compare results with the reference data
+TOLERANCE = 1.e-7
+features = Part_1_doc.allFeatures()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 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
+#
+
+from GeomAlgoAPI import *
+from ModelAPI import *
+from SketchAPI import *
+from salome.shaper import model
+
+import os
+import math
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Point_1 = model.addPoint(Part_1_doc, 100, 100, 100)
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 30)
+model.do()
+Axis_1 = model.addAxis(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("VERTEX", "Point_1"))
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection("EDGE", "Axis_1"), 100, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchLine_1 = Sketch_2.addLine(57.73502691896258, 57.73502691896258, 71.87716254269353, 43.59289129523163)
+SketchLine_2 = Sketch_2.addLine(71.87716254269353, 43.59289129523163, 71.87716254269353, 71.87716254269353)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(71.87716254269353, 71.87716254269353, 57.73502691896258, 57.73502691896258)
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintPerpendicular_1 = Sketch_2.setPerpendicular(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintVertical_1 = Sketch_2.setVertical(SketchLine_2.result())
+SketchConstraintEqual_1 = Sketch_2.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_1.startPoint())
+SketchConstraintLength_1 = Sketch_2.setLength(SketchLine_1.result(), 20)
+model.do()
+Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection("EDGE", "PartSet/OX"), 180, 0)
+model.do()
+model.end()
+
+# store the reference data
+features = Part_1_doc.allFeatures()
+refData = []
+for feat in features:
+ res = []
+ for r in feat.results():
+ res.append(GeomAlgoAPI_ShapeTools.volume(r.shape()))
+ refData.append( (feat.getKind(), res) )
+
+filename = 'check_export.shaperpart'
+model.removeFile(filename)
+
+# emport the document
+model.begin()
+model.exportPart(Part_1_doc, filename)
+model.end()
+assert os.path.exists(filename), "ERROR: Cannot export {}".format(Part_1.name())
+
+# close all documents
+model.reset()
+
+# import the document
+model.begin()
+partSet = model.moduleDocument()
+model.importPart(partSet, filename)
+model.end()
+
+# Test 1. New Part should be created
+assert(partSet.size(ModelAPI_ResultPart.group()) == 1)
+newPart = modelAPI_ResultPart(objectToResult(partSet.object(ModelAPI_ResultPart.group(), 0)))
+newPart_doc = newPart.partDoc()
+
+# Test 2. Compare results with the reference data
+TOLERANCE = 1.e-7
+features = newPart_doc.allFeatures()
+assert(len(features) == len(refData))
+for feat, ref in zip(features, refData):
+ assert(feat.getKind() == ref[0])
+ for fv, rv in zip(feat.results(), ref[1]):
+ assert(math.fabs(GeomAlgoAPI_ShapeTools.volume(fv.shape()) - rv) < TOLERANCE)
+
+assert(model.checkPythonDump())
<source path="export_widget.xml" />
</feature>
<feature id="Dump" title="Dump" tooltip="Dump Python script" icon="icons/Exchange/dump.png"
- helpfile="dumpFeature.html">
+ helpfile="dumpFeature.html" abort_confirmation="false">
<export_file_selector id="file_path"
type="save"
title="Dump to file"
tooltip="To use geometrical order for identification of selected shapes"
default="false"/> -->
</feature>
+
+ <feature id="ImportPart" title="Import part" tooltip="Import features from file" icon="icons/Exchange/import_part.png"
+ helpfile="importPart.html"
+ internal="1">
+ <file_selector id="file_path" title="Import file" path="">
+ <validator id="ExchangePlugin_ImportFormat" parameters="shaperpart:Part" />
+ </file_selector>
+ <choice id="target_part"
+ string_list_attribute="target_parts_list"
+ label="Import to"
+ tooltip="Select the part to import the document" />
+ </feature>
+ <feature id="ExportPart" title="Export part" tooltip="Export structure of the Part to file" icon="icons/Exchange/export_part.png"
+ helpfile="exportPart.html"
+ internal="1">
+ <export_file_selector id="file_path"
+ type="save"
+ title="Export file"
+ path="">
+ <validator id="ExchangePlugin_ExportFormat"
+ parameters="shaperpart:Part" />
+ </export_file_selector>
+ <multi_selector id="selection_list"
+ tooltip="Select features or results"
+ shape_types="Vertices Edges Faces Solids Compsolids Objects">
+ <validator id="GeomValidators_GlobalSelection" />
+ <validator id="ExchangePlugin_InHistory" />
+ </multi_selector>
+ </feature>
</group>
</workbench>
</plugin>
\ No newline at end of file
theDumper << ", " << anAttrToObject << ", " << anAttrToOffset <<
", " << anAttrFromObject << ", " << anAttrFromOffset;
+ } else {
+ // Through all
}
AttributeSelectionListPtr anAttrBoolObjects =
initialize();
}
+//==================================================================================================
+FeaturesAPI_ExtrusionCut::FeaturesAPI_ExtrusionCut(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+: FeaturesAPI_ExtrusionBoolean(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theBaseObjects, mybaseObjects);
+ fillAttribute(FeaturesPlugin_Extrusion::CREATION_METHOD_THROUGH_ALL(), mycreationMethod);
+ setBooleanObjects(theBooleanObjects);
+ }
+}
+
//==================================================================================================
FeaturesAPI_ExtrusionCut::FeaturesAPI_ExtrusionCut(
const std::shared_ptr<ModelAPI_Feature>& theFeature,
}
}
+//==================================================================================================
+FeaturesAPI_ExtrusionCut::FeaturesAPI_ExtrusionCut(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+: FeaturesAPI_ExtrusionBoolean(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theBaseObjects, mybaseObjects);
+ fillAttribute(theDirection, mydirection);
+ fillAttribute(FeaturesPlugin_Extrusion::CREATION_METHOD_THROUGH_ALL(), mycreationMethod);
+ setBooleanObjects(theBooleanObjects);
+ }
+}
+
//==================================================================================================
FeaturesAPI_ExtrusionCut::FeaturesAPI_ExtrusionCut(
const std::shared_ptr<ModelAPI_Feature>& theFeature,
}
}
+//==================================================================================================
+ExtrusionCutPtr addExtrusionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ thePart->addFeature(FeaturesPlugin_ExtrusionCut::ID());
+ return ExtrusionCutPtr(new FeaturesAPI_ExtrusionCut(aFeature, theBaseObjects,
+ theBooleanObjects));
+}
+
//==================================================================================================
ExtrusionCutPtr addExtrusionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects,
theSize, theBooleanObjects));
}
+//==================================================================================================
+ExtrusionCutPtr addExtrusionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ thePart->addFeature(FeaturesPlugin_ExtrusionCut::ID());
+ return ExtrusionCutPtr(new FeaturesAPI_ExtrusionCut(aFeature, theBaseObjects, theDirection,
+ theBooleanObjects));
+}
+
//==================================================================================================
ExtrusionCutPtr addExtrusionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects,
initialize();
}
+//==================================================================================================
+FeaturesAPI_ExtrusionFuse::FeaturesAPI_ExtrusionFuse(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+: FeaturesAPI_ExtrusionBoolean(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theBaseObjects, mybaseObjects);
+ fillAttribute(FeaturesPlugin_Extrusion::CREATION_METHOD_THROUGH_ALL(), mycreationMethod);
+ setBooleanObjects(theBooleanObjects);
+ }
+}
+
//==================================================================================================
FeaturesAPI_ExtrusionFuse::FeaturesAPI_ExtrusionFuse(
const std::shared_ptr<ModelAPI_Feature>& theFeature,
}
}
+//==================================================================================================
+FeaturesAPI_ExtrusionFuse::FeaturesAPI_ExtrusionFuse(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+: FeaturesAPI_ExtrusionBoolean(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theBaseObjects, mybaseObjects);
+ fillAttribute(theDirection, mydirection);
+ fillAttribute(FeaturesPlugin_Extrusion::CREATION_METHOD_THROUGH_ALL(), mycreationMethod);
+ setBooleanObjects(theBooleanObjects);
+ }
+}
+
//==================================================================================================
FeaturesAPI_ExtrusionFuse::FeaturesAPI_ExtrusionFuse(
const std::shared_ptr<ModelAPI_Feature>& theFeature,
}
}
+//==================================================================================================
+ExtrusionFusePtr addExtrusionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ thePart->addFeature(FeaturesPlugin_ExtrusionFuse::ID());
+ return ExtrusionFusePtr(new FeaturesAPI_ExtrusionFuse(aFeature, theBaseObjects,
+ theBooleanObjects));
+}
+
//==================================================================================================
ExtrusionFusePtr addExtrusionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects,
theSize, theBooleanObjects));
}
+//==================================================================================================
+ExtrusionFusePtr addExtrusionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ thePart->addFeature(FeaturesPlugin_ExtrusionFuse::ID());
+ return ExtrusionFusePtr(new FeaturesAPI_ExtrusionFuse(aFeature, theBaseObjects,
+ theDirection, theBooleanObjects));
+}
+
//==================================================================================================
ExtrusionFusePtr addExtrusionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects,
FEATURESAPI_EXPORT
explicit FeaturesAPI_ExtrusionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_ExtrusionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// Constructor with values.
FEATURESAPI_EXPORT
explicit FeaturesAPI_ExtrusionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const ModelHighAPI_Double& theSize,
const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_ExtrusionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// Constructor with values.
FEATURESAPI_EXPORT
explicit FeaturesAPI_ExtrusionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature,
/// Pointer on ExtrusionCut object.
typedef std::shared_ptr<FeaturesAPI_ExtrusionCut> ExtrusionCutPtr;
+/// \ingroup CPPHighAPI
+/// \brief Create ExtrusionCut feature.
+FEATURESAPI_EXPORT
+ExtrusionCutPtr addExtrusionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// \ingroup CPPHighAPI
/// \brief Create ExtrusionCut feature.
FEATURESAPI_EXPORT
const ModelHighAPI_Double& theSize,
const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+/// \ingroup CPPHighAPI
+/// \brief Create ExtrusionCut feature.
+FEATURESAPI_EXPORT
+ExtrusionCutPtr addExtrusionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// \ingroup CPPHighAPI
/// \brief Create ExtrusionCut feature.
FEATURESAPI_EXPORT
FEATURESAPI_EXPORT
explicit FeaturesAPI_ExtrusionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_ExtrusionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// Constructor with values.
FEATURESAPI_EXPORT
explicit FeaturesAPI_ExtrusionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const ModelHighAPI_Double& theSize,
const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_ExtrusionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// Constructor with values.
FEATURESAPI_EXPORT
explicit FeaturesAPI_ExtrusionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
/// Pointer on ExtrusionFuse object.
typedef std::shared_ptr<FeaturesAPI_ExtrusionFuse> ExtrusionFusePtr;
+/// \ingroup CPPHighAPI
+/// \brief Create ExtrusionFuse feature.
+FEATURESAPI_EXPORT
+ExtrusionFusePtr addExtrusionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// \ingroup CPPHighAPI
/// \brief Create ExtrusionFuse feature.
FEATURESAPI_EXPORT
const ModelHighAPI_Double& theSize,
const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+/// \ingroup CPPHighAPI
+/// \brief Create ExtrusionFuse feature.
+FEATURESAPI_EXPORT
+ExtrusionFusePtr addExtrusionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theDirection,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// \ingroup CPPHighAPI
/// \brief Create ExtrusionFuse feature.
FEATURESAPI_EXPORT
//==================================================================================================
void FeaturesAPI_RevolutionBoolean::setPlanesAndOffsets(const ModelHighAPI_Selection& theToObject,
const ModelHighAPI_Double& theToOffset,
- const ModelHighAPI_Selection& theFromObject,
+ const ModelHighAPI_Selection& theFromObject,
const ModelHighAPI_Double& theFromOffset)
{
fillAttribute(FeaturesPlugin_Revolution::CREATION_METHOD_BY_PLANES(), mycreationMethod);
theDumper << ", " << anAttrToObject << ", " << anAttrToOffset <<
", " << anAttrFromObject << ", " << anAttrFromOffset;
+ } else {
+ // Through All
}
AttributeSelectionListPtr anAttrBoolObjects =
initialize();
}
+//==================================================================================================
+FeaturesAPI_RevolutionCut::FeaturesAPI_RevolutionCut(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+: FeaturesAPI_RevolutionBoolean(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theBaseObjects, mybaseObjects);
+ fillAttribute(theAxis, myaxis);
+ fillAttribute(FeaturesPlugin_Revolution::CREATION_METHOD_THROUGH_ALL(), mycreationMethod);
+ setBooleanObjects(theBooleanObjects);
+ }
+}
+
//==================================================================================================
FeaturesAPI_RevolutionCut::FeaturesAPI_RevolutionCut(
const std::shared_ptr<ModelAPI_Feature>& theFeature,
}
}
+//==================================================================================================
+RevolutionCutPtr addRevolutionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ thePart->addFeature(FeaturesPlugin_RevolutionCut::ID());
+ return RevolutionCutPtr(new FeaturesAPI_RevolutionCut(aFeature, theBaseObjects,
+ theAxis, theBooleanObjects));
+}
+
//==================================================================================================
RevolutionCutPtr addRevolutionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects,
initialize();
}
+//==================================================================================================
+FeaturesAPI_RevolutionFuse::FeaturesAPI_RevolutionFuse(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+: FeaturesAPI_RevolutionBoolean(theFeature)
+{
+ if(initialize()) {
+ fillAttribute(theBaseObjects, mybaseObjects);
+ fillAttribute(theAxis, myaxis);
+ fillAttribute(FeaturesPlugin_Revolution::CREATION_METHOD_THROUGH_ALL(), mycreationMethod);
+ setBooleanObjects(theBooleanObjects);
+ }
+}
+
//==================================================================================================
FeaturesAPI_RevolutionFuse::FeaturesAPI_RevolutionFuse(
const std::shared_ptr<ModelAPI_Feature>& theFeature,
}
}
+//==================================================================================================
+RevolutionFusePtr addRevolutionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ thePart->addFeature(FeaturesPlugin_RevolutionFuse::ID());
+ return RevolutionFusePtr(new FeaturesAPI_RevolutionFuse(aFeature, theBaseObjects,
+ theAxis, theBooleanObjects));
+}
+
//==================================================================================================
RevolutionFusePtr addRevolutionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
const std::list<ModelHighAPI_Selection>& theBaseObjects,
FEATURESAPI_EXPORT
explicit FeaturesAPI_RevolutionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_RevolutionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// Constructor with values.
FEATURESAPI_EXPORT
explicit FeaturesAPI_RevolutionCut(const std::shared_ptr<ModelAPI_Feature>& theFeature,
/// Pointer on RevolutionCut object.
typedef std::shared_ptr<FeaturesAPI_RevolutionCut> RevolutionCutPtr;
+/// \ingroup CPPHighAPI
+/// \brief Create RevolutionCut feature.
+FEATURESAPI_EXPORT
+RevolutionCutPtr addRevolutionCut(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// \ingroup CPPHighAPI
/// \brief Create RevolutionCut feature.
FEATURESAPI_EXPORT
FEATURESAPI_EXPORT
explicit FeaturesAPI_RevolutionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+ /// Constructor with values.
+ FEATURESAPI_EXPORT
+ explicit FeaturesAPI_RevolutionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// Constructor with values.
FEATURESAPI_EXPORT
explicit FeaturesAPI_RevolutionFuse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
/// Pointer on RevolutionFuse object.
typedef std::shared_ptr<FeaturesAPI_RevolutionFuse> RevolutionFusePtr;
+/// \ingroup CPPHighAPI
+/// \brief Create RevolutionFuse feature.
+FEATURESAPI_EXPORT
+RevolutionFusePtr addRevolutionFuse(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::list<ModelHighAPI_Selection>& theBaseObjects,
+ const ModelHighAPI_Selection& theAxis,
+ const std::list<ModelHighAPI_Selection>& theBooleanObjects);
+
/// \ingroup CPPHighAPI
/// \brief Create RevolutionFuse feature.
FEATURESAPI_EXPORT
SET(TEXT_RESOURCES
FeaturesPlugin_msg_en.ts
+ FeaturesPlugin_msg_fr.ts
FeaturesPlugin_msg_ru.ts
)
TestExtrusionCut_BySize.py
TestExtrusionCut_ByPlanesAndOffsets.py
TestExtrusionCut_ByFaces.py
+ TestExtrusionCut_ThroughAll.py
TestExtrusionFuse.py
TestExtrusionFuse_BySize.py
TestExtrusionFuse_ByPlanesAndOffsets.py
+ TestExtrusionFuse_ThroughAll.py
TestExtrusion_ErrorMsg.py
TestExtrusion_ZeroOffsetError.py
TestExtrusion_ByFaces01.py
TestRevolutionCut.py
TestRevolutionCut_ByAngle.py
TestRevolutionCut_ByPlanesAndOffsets.py
+ TestRevolutionCut_ThroughAll.py
TestRevolutionFuse.py
TestRevolutionFuse_ByAngle.py
TestRevolutionFuse_ByPlanesAndOffsets.py
+ TestRevolutionFuse_ThroughAll.py
TestCompositeFeaturesOnCompSolids.py
TestPartition.py
TestPartition_ErrorMsg.py
/// Request for initialization of data model of the feature: adding all attributes.
FEATURESPLUGIN_EXPORT virtual void initAttributes();
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
public:
/// Request for initialization of data model of the feature: adding all attributes.
FEATURESPLUGIN_EXPORT virtual void initAttributes();
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
public:
/// Request for initialization of data model of the feature: adding all attributes.
FEATURESPLUGIN_EXPORT virtual void initAttributes();
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
public:
// Collecting solids from compsolids which will not be modified
// in boolean operation and will be added to result.
+ bool isProcessCompsolid = !isSimpleCreation || aFuseVersion >= THE_VERSION_1;
ListOfShape aShapesToAdd;
for (ObjectHierarchy::Iterator anObjectsIt = anObjectsHierarchy.Begin();
- !isSimpleCreation && anObjectsIt != anObjectsHierarchy.End();
+ isProcessCompsolid && anObjectsIt != anObjectsHierarchy.End();
++anObjectsIt) {
GeomShapePtr anObject = *anObjectsIt;
GeomShapePtr aParent = anObjectsHierarchy.Parent(anObject, false);
aMakeShapeList->appendAlgo(aCutAlgo);
}
}
- anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
- anEdgesAndFaces.end());
+
+ if (aShapesToAdd.empty() || !aCuttedEdgesAndFaces) {
+ anOriginalShapes.insert(anOriginalShapes.end(), anEdgesAndFaces.begin(),
+ anEdgesAndFaces.end());
+ }
// If we have compsolids then cut with not used solids all others.
if (!aShapesToAdd.empty()) {
/// Request for initialization of data model of the feature: adding all attributes.
FEATURESPLUGIN_EXPORT virtual void initAttributes();
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
public:
/// Request for initialization of data model of the feature: adding all attributes.
FEATURESPLUGIN_EXPORT virtual void initAttributes();
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
public:
return MY_ANGLE_ID;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_OBJECTS_ID;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void executeCompositeBoolean();
protected:
getBaseShapes(theBaseShapes);
//Getting direction.
- static const std::string aSelectionError = "Error: The direction shape selection is bad.";
- AttributeSelectionPtr aSelection = selection(DIRECTION_OBJECT_ID());
- GeomShapePtr aShape = aSelection->value();
- if (!aShape.get()) {
- if (aSelection->context().get()) {
- aShape = aSelection->context()->shape();
- }
- }
-
- GeomEdgePtr anEdge;
- if (aShape.get()) {
- if (aShape->isEdge())
- {
- anEdge = aShape->edge();
- }
- else if (aShape->isCompound())
- {
- GeomAPI_ShapeIterator anIt(aShape);
- anEdge = anIt.current()->edge();
- }
- }
-
std::shared_ptr<GeomAPI_Dir> aDir;
- if(anEdge.get()) {
- if(anEdge->isLine()) {
- aDir = anEdge->line()->direction();
- }
- }
+ getDirection(aDir);
// Getting sizes.
double aToSize = 0.0;
double aFromSize = 0.0;
-
- if(string(CREATION_METHOD())->value() == CREATION_METHOD_BY_SIZES()) {
- aToSize = real(TO_SIZE_ID())->value();
- aFromSize = real(FROM_SIZE_ID())->value();
- } else {
- aToSize = real(TO_OFFSET_ID())->value();
- aFromSize = real(FROM_OFFSET_ID())->value();
- }
+ getSizes(aToSize, aFromSize);
// Getting bounding planes.
GeomShapePtr aToShape;
GeomShapePtr aFromShape;
if(string(CREATION_METHOD())->value() == CREATION_METHOD_BY_PLANES()) {
- aSelection = selection(TO_OBJECT_ID());
+ AttributeSelectionPtr aSelection = selection(TO_OBJECT_ID());
if(aSelection.get()) {
aToShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aSelection->value());
if(!aToShape.get() && aSelection->context().get()) {
setResult(aResultBody, theIndex);
}
+
+//=================================================================================================
+void FeaturesPlugin_Extrusion::getDirection(std::shared_ptr<GeomAPI_Dir>& theDir)
+{
+ static const std::string aSelectionError = "Error: The direction shape selection is bad.";
+ AttributeSelectionPtr aSelection = selection(DIRECTION_OBJECT_ID());
+ GeomShapePtr aShape = aSelection->value();
+ if (!aShape.get()) {
+ if (aSelection->context().get()) {
+ aShape = aSelection->context()->shape();
+ }
+ }
+
+ GeomEdgePtr anEdge;
+ if (aShape.get()) {
+ if (aShape->isEdge())
+ {
+ anEdge = aShape->edge();
+ }
+ else if (aShape->isCompound())
+ {
+ GeomAPI_ShapeIterator anIt(aShape);
+ anEdge = anIt.current()->edge();
+ }
+ }
+
+ if (anEdge.get()) {
+ if (anEdge->isLine()) {
+ theDir = anEdge->line()->direction();
+ }
+ }
+}
+
+//=================================================================================================
+void FeaturesPlugin_Extrusion::getSizes(double& theToSize, double& theFromSize)
+{
+ if (string(CREATION_METHOD())->value() == CREATION_METHOD_BY_SIZES()) {
+ theToSize = real(TO_SIZE_ID())->value();
+ theFromSize = real(FROM_SIZE_ID())->value();
+ } if (string(CREATION_METHOD())->value() == CREATION_METHOD_BY_PLANES()) {
+ theToSize = real(TO_OFFSET_ID())->value();
+ theFromSize = real(FROM_OFFSET_ID())->value();
+ } else {
+ }
+}
return MY_CREATION_METHOD_ID;
}
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_THROUGH_ALL()
+ {
+ static const std::string MY_CREATION_METHOD_ID("ThroughAll");
+ return MY_CREATION_METHOD_ID;
+ }
+
/// Attribute name of an object to which the extrusion grows.
inline static const std::string& DIRECTION_OBJECT_ID()
{
/// Request for initialization of data model of the feature: adding all attributes.
FEATURESPLUGIN_EXPORT virtual void initAttributes();
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
protected:
const ListOfShape& theBoundaryShapes,
const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
const int theIndex = 0);
+
+ /// Retrieve direction argument.
+ void getDirection(std::shared_ptr<GeomAPI_Dir>& theDir);
+
+ /// Retrieve or calculate prism sizes.
+ virtual void getSizes(double& theToSize, double& theFromSize);
};
#endif
#include "FeaturesPlugin_ExtrusionBoolean.h"
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_AttributeString.h>
+
+#include <GeomAlgoAPI_ShapeTools.h>
+
//=================================================================================================
void FeaturesPlugin_ExtrusionBoolean::initAttributes()
{
{
FeaturesPlugin_Extrusion::storeGenerationHistory(theResultBody, theBaseShape, theMakeShape);
}
+
+//=================================================================================================
+void FeaturesPlugin_ExtrusionBoolean::getSizes(double& theToSize, double& theFromSize)
+{
+ if (string(CREATION_METHOD())->value() != CREATION_METHOD_THROUGH_ALL()) {
+ FeaturesPlugin_Extrusion::getSizes(theToSize, theFromSize);
+ } else {
+ // Getting objects.
+ ListOfShape anObjects;
+ AttributeSelectionListPtr anObjectsSelList = myFeature->selectionList(OBJECTS_ID());
+ for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
+ AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
+ GeomShapePtr anObject = anObjectAttr->value();
+ if (!anObject.get()) {
+ myFeature->setError("Error: Could not get object.");
+ return;
+ }
+ anObjects.push_back(anObject);
+ }
+
+ // Getting prism bases.
+ ListOfShape aBaseShapes;
+ getBaseShapes(aBaseShapes);
+
+ // Getting prism direction.
+ std::shared_ptr<GeomAPI_Dir> aDir;
+ getDirection(aDir);
+
+ // Calculate sizes
+ GeomAlgoAPI_ShapeTools::computeThroughAll(anObjects, aBaseShapes, aDir, theToSize, theFromSize);
+ }
+}
void storeGenerationHistory(ResultBodyPtr theResultBody,
const GeomShapePtr theBaseShape,
const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
+
+ /// Calculate prism sizes to ensure that it passes through all objects
+ /// Redefined from FeaturesPlugin_Extrusion
+ virtual void getSizes(double& theToSize, double& theFromSize);
};
#endif
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
};
#include "FeaturesPlugin_ExtrusionFuse.h"
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_AttributeSelectionList.h>
+
+#include <GeomAlgoAPI_Boolean.h>
+#include <GeomAlgoAPI_Prism.h>
+#include <GeomAlgoAPI_ThroughAll.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+
//=================================================================================================
FeaturesPlugin_ExtrusionFuse::FeaturesPlugin_ExtrusionFuse()
{
//=================================================================================================
void FeaturesPlugin_ExtrusionFuse::execute()
{
- executeCompositeBoolean();
+ if (string(CREATION_METHOD())->value() != CREATION_METHOD_THROUGH_ALL())
+ executeCompositeBoolean();
+ else {
+ executeFuseThroughAll();
+ }
+}
+
+//=================================================================================================
+void FeaturesPlugin_ExtrusionFuse::executeFuseThroughAll()
+{
+ // Getting objects.
+ ListOfShape anObjects;
+ AttributeSelectionListPtr anObjectsSelList = myFeature->selectionList(OBJECTS_ID());
+ for (int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
+ AttributeSelectionPtr anObjectAttr = anObjectsSelList->value(anObjectsIndex);
+ GeomShapePtr anObject = anObjectAttr->value();
+ if (!anObject.get()) {
+ myFeature->setError("Error: Could not get object.");
+ return;
+ }
+ anObjects.push_back(anObject);
+ }
+
+ // Make generation.
+ ListOfShape aGenBaseShapes;
+ ListOfMakeShape aGenMakeShapes;
+ if (!makeGeneration(aGenBaseShapes, aGenMakeShapes)) {
+ return;
+ }
+
+ // Getting tools.
+ ListOfShape aNewTools;
+ ListOfMakeShape aToolsMakeShapes;
+ for (ListOfMakeShape::const_iterator
+ anIt = aGenMakeShapes.cbegin(); anIt != aGenMakeShapes.cend(); ++anIt) {
+ GeomMakeShapePtr anAlgo = (*anIt);
+ std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo =
+ std::dynamic_pointer_cast<GeomAlgoAPI_Prism>(anAlgo);
+
+ // Cut the prism by all objects and throw away end pieces
+ std::shared_ptr<GeomAlgoAPI_ThroughAll> aToolAlgo (
+ new GeomAlgoAPI_ThroughAll(aPrismAlgo, anObjects));
+
+ // Checking that the algorithm worked properly
+ if (!aToolAlgo->isDone() || aToolAlgo->shape()->isNull() || !aToolAlgo->isValid()) {
+ myFeature->setError("Error: ThroughAll algorithm failed.");
+ } else {
+ GeomShapePtr aCuttedTool = aToolAlgo->shape();
+ aNewTools.push_back(aCuttedTool);
+ aToolsMakeShapes.push_back(aToolAlgo);
+ }
+ }
+
+ // Perform FeaturesPlugin_CompositeBoolean::makeBoolean() with new (cutted) tools
+ ListOfShape aBooleanObjects;
+ ListOfMakeShape aBooleanMakeShapes;
+ if (!makeBoolean(aNewTools, aBooleanObjects, aBooleanMakeShapes)) {
+ return;
+ }
+
+ if (myOperationType == BOOL_FUSE) {
+ aNewTools.splice(aNewTools.begin(), aBooleanObjects);
+ aBooleanObjects.splice(aBooleanObjects.begin(), aNewTools, aNewTools.begin());
+ }
+
+ // 4. Store result (like in FeaturesPlugin_CompositeBoolean::executeCompositeBoolean())
+ int aResultIndex = 0;
+ std::vector<ResultBaseAlgo> aResultBaseAlgoList;
+ ListOfShape aResultShapesList;
+ ListOfShape::const_iterator aBoolObjIt = aBooleanObjects.cbegin();
+ ListOfMakeShape::const_iterator aBoolMSIt = aBooleanMakeShapes.cbegin();
+ for(; aBoolObjIt != aBooleanObjects.cend() && aBoolMSIt != aBooleanMakeShapes.cend();
+ ++aBoolObjIt, ++aBoolMSIt) {
+
+ ResultBodyPtr aResultBody = myFeature->document()->createBody(myFeature->data(), aResultIndex);
+
+ if((*aBoolObjIt)->isEqual((*aBoolMSIt)->shape())) {
+ aResultBody->store((*aBoolMSIt)->shape(), false);
+ }
+ else
+ {
+ aResultBody->storeModified(*aBoolObjIt, (*aBoolMSIt)->shape());
+
+ // Store generation history.
+ ListOfShape::const_iterator aGenBaseIt = aGenBaseShapes.cbegin();
+ ListOfMakeShape::const_iterator aGenMSIt = aGenMakeShapes.cbegin();
+ for(; aGenBaseIt != aGenBaseShapes.cend() && aGenMSIt != aGenMakeShapes.cend();
+ ++aGenBaseIt, ++aGenMSIt) {
+
+ // ???
+ ListOfMakeShape::const_iterator aToolsMSIt = aToolsMakeShapes.cbegin();
+ for(; aToolsMSIt != aToolsMakeShapes.cend(); ++aToolsMSIt) {
+ std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMSList(new GeomAlgoAPI_MakeShapeList());
+
+ // prism generation
+ aMSList->appendAlgo(*aGenMSIt);
+
+ // tool modification (cut by objects)
+ aMSList->appendAlgo(*aToolsMSIt);
+
+ // bool fuse
+ aMSList->appendAlgo(*aBoolMSIt);
+ storeGenerationHistory(aResultBody, *aGenBaseIt, aMSList);
+ }
+ }
+
+ storeModificationHistory(aResultBody, *aBoolObjIt, aNewTools, *aBoolMSIt);
+
+ ResultBaseAlgo aRBA;
+ aRBA.resultBody = aResultBody;
+ aRBA.baseShape = *aBoolObjIt;
+ aRBA.makeShape = *aBoolMSIt;
+ aResultBaseAlgoList.push_back(aRBA);
+ aResultShapesList.push_back((*aBoolMSIt)->shape());
+ }
+
+ myFeature->setResult(aResultBody, aResultIndex++);
+ }
+
+ // 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);
+ storeDeletedShapes(aResultBaseAlgoList, aNewTools, aResultShapesCompound);
+
+ myFeature->removeResults(aResultIndex);
}
/// fuse result with other objects in a single operation.
class FeaturesPlugin_ExtrusionFuse : public FeaturesPlugin_ExtrusionBoolean
{
-public:
+ public:
/// Use plugin manager for features creation.
FeaturesPlugin_ExtrusionFuse();
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
+
+ private:
+ void executeFuseThroughAll();
};
#endif
return START_RADIUS_ID();
}
- /// Creates a new part document if needed.
+ /// Performs the fillet algorithm and stores it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_RESULT_VALUES_ID;
}
- /// Creates a new part document if needed
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes
return MY_KIND;
}
- /// Creates a new part document if needed
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes
return MY_KIND;
}
- /// Creates a new part document if needed
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes
return MY_KIND;
}
- /// Creates a new part document if needed
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes
/// \param[in] theID identifier of changed attribute.
FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
private:
double aToAngle = 0.0;
double aFromAngle = 0.0;
- if(string(CREATION_METHOD())->value() == CREATION_METHOD_BY_ANGLES()) {
+ if (string(CREATION_METHOD())->value() == CREATION_METHOD_BY_ANGLES()) {
aToAngle = real(TO_ANGLE_ID())->value();
aFromAngle = real(FROM_ANGLE_ID())->value();
- } else {
+ } else if (string(CREATION_METHOD())->value() == CREATION_METHOD_BY_PLANES()) {
aToAngle = real(TO_OFFSET_ID())->value();
aFromAngle = real(FROM_OFFSET_ID())->value();
+ } else if (string(CREATION_METHOD())->value() == CREATION_METHOD_THROUGH_ALL()) {
+ aToAngle = 360.0;
+ aFromAngle = 0.0;
+ } else {
}
// Getting bounding planes.
return MY_CREATION_METHOD_ID;
}
+ /// Attribute name for creation method.
+ inline static const std::string& CREATION_METHOD_THROUGH_ALL()
+ {
+ static const std::string MY_CREATION_METHOD_ID("ThroughAll");
+ return MY_CREATION_METHOD_ID;
+ }
+
/// Attribute name for creation method.
inline static const std::string& CREATION_METHOD_BY_ANGLES()
{
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
};
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
};
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed.
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes.
return MY_KIND;
}
- /// Creates a new part document if needed
+ /// Performs the algorithm and stores results it in the data structure.
FEATURESPLUGIN_EXPORT virtual void execute();
/// Request for initialization of data model of the feature: adding all attributes
if (anObjectsNb + aToolsNb < 2) {
theError = "Not enough arguments for Fuse operation.";
return false;
- } else if (isAllInSameCompSolid) {
- theError = "Operations only between sub-shapes of the same shape not allowed.";
- return false;
}
return true;
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <!-- workshop -->
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Features</source>
+ <translation>Caractéristiques</translation>
+ </message>
+ <message>
+ <source>Common</source>
+ <translation>Intersection</translation>
+ </message>
+ <message>
+ <source>Cut</source>
+ <translation>Découpe</translation>
+ </message>
+ <message>
+ <source>Extrusion</source>
+ <translation>Extrusion</translation>
+ </message>
+ <message>
+ <source>ExtrusionCut</source>
+ <translation>Enlèvement de matière extrudé</translation>
+ </message>
+ <message>
+ <source>ExtrusionFuse</source>
+ <translation>Bossage extrudé</translation>
+ </message>
+ <message>
+ <source>Fillet</source>
+ <translation>Congé</translation>
+ </message>
+ <message>
+ <source>Fuse</source>
+ <translation>Fusionner</translation>
+ </message>
+ <message>
+ <source>Fuse Faces</source>
+ <translation>Fusionner des faces</translation>
+ </message>
+ <message>
+ <source>Intersection</source>
+ <translation>Section</translation>
+ </message>
+ <message>
+ <source>Partition</source>
+ <translation>Partition</translation>
+ </message>
+ <message>
+ <source>Pipe</source>
+ <translation>Tuyau</translation>
+ </message>
+ <message>
+ <source>Recover</source>
+ <translation>Récupérer</translation>
+ </message>
+ <message>
+ <source>Remove Sub-Shapes</source>
+ <translation>Supprimer les sous-formes</translation>
+ </message>
+ <message>
+ <source>Revolution</source>
+ <translation>Révolution</translation>
+ </message>
+ <message>
+ <source>RevolutionCut</source>
+ <translation>Enlèvement de matière avec révolution</translation>
+ </message>
+ <message>
+ <source>RevolutionFuse</source>
+ <translation>Bossage avec révolution</translation>
+ </message>
+ <message>
+ <source>Scale</source>
+ <translation>Échelle</translation>
+ </message>
+ <message>
+ <source>Smash</source>
+ <translation>Smash</translation>
+ </message>
+ <message>
+ <source>Split</source>
+ <translation>Diviser</translation>
+ </message>
+ <message>
+ <source>Union</source>
+ <translation>Réunion</translation>
+ </message>
+ <!-- Part menu -->
+ <message>
+ <source>Angular Copy</source>
+ <translation>Copie angulaire</translation>
+ </message>
+ <message>
+ <source>Linear copy</source>
+ <translation>Copie linéaire</translation>
+ </message>
+ <message>
+ <source>Measurement</source>
+ <translation>Mesure</translation>
+ </message>
+ <message>
+ <source>Placement</source>
+ <translation>Placement</translation>
+ </message>
+ <message>
+ <source>Rotation</source>
+ <translation>Rotation</translation>
+ </message>
+ <message>
+ <source>Symmetry</source>
+ <translation>Symétrie</translation>
+ </message>
+ <message>
+ <source>Translation</source>
+ <translation>Translation</translation>
+ </message>
+ </context>
+
+ <!-- Common -->
+ <context>
+ <name>Common</name>
+ <message>
+ <source>Common</source>
+ <translation>Intersection</translation>
+ </message>
+ <message>
+ <source>Perform boolean common operation with objects</source>
+ <translation>Effectuer l’opération booléenne section avec des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Common:FeaturesPlugin_ValidatorBooleanCommonArguments</name>
+ <message>
+ <source>Not enough arguments for Fuse operation.</source>
+ <translation>Pas assez d'arguments pour l'opération Fusionner.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Common:creation_method</name>
+ <message>
+ <source>Simple</source>
+ <translation>Simple</translation>
+ </message>
+ <message>
+ <source>advanced</source>
+ <translation>avancée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Common:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Objects</source>
+ <translation>Objets</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Common:tool_objects</name>
+ <message>
+ <source>Select tools</source>
+ <translation>Sélectionnez des outils</translation>
+ </message>
+ <context>
+ <name>Common:tool_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez des outils.</translation>
+ </message>
+ </context>
+ <message>
+ <source>Tool objects</source>
+ <translation>Objets outils</translation>
+ </message>
+ </context>
+ <context>
+ <name>Model_Data</name>
+ <message>
+ <source>%1 has failed during the update</source>
+ <translation>%1 a échoué lors de la mise à jour</translation>
+ </message>
+ </context>
+
+ <!-- Cut -->
+ <context>
+ <name>Cut</name>
+ <message>
+ <source>Cut</source>
+ <translation>Découpe</translation>
+ </message>
+ <message>
+ <source>Perform boolean cut operation with objects</source>
+ <translation>Effectuer l’opération booléenne découpe avec des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cut:FeaturesPlugin_ValidatorBooleanArguments</name>
+ <message>
+ <source>Objects not selected.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cut:FeaturesPlugin_ValidatorBooleanArguments</name>
+ <message>
+ <source>Tools not selected.</source>
+ <translation>Les objets outils ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cut:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cut:tool_objects</name>
+ <message>
+ <source>Select tools</source>
+ <translation>Sélectionnez des outils</translation>
+ </message>
+ <message>
+ <source>Tool objects</source>
+ <translation>Objets outils</translation>
+ </message>
+ </context>
+
+ <!-- Extrusion -->
+ <context>
+ <name>Extrusion</name>
+ <message>
+ <source>Create a solid by extrusion of a face</source>
+ <translation>Créer un solide par extrusion d'une face</translation>
+ </message>
+ <message>
+ <source>Extrusion</source>
+ <translation>Extrusion</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:CreationMethod</name>
+ <message>
+ <source>By bounding faces and offsets</source>
+ <translation>En délimitant les faces et les décalages</translation>
+ </message>
+ <message>
+ <source>By sizes</source>
+ <translation>Par tailles</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base</name>
+ <message>
+ <source>Base objects:</source>
+ <translation>Objets de base:</translation>
+ </message>
+ <message>
+ <source>Select a base objects</source>
+ <translation>Sélectionnez un objet de base</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un objet de base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object</name>
+ <message>
+ <source>Direction</source>
+ <translation>Direction</translation>
+ </message>
+ <message>
+ <source>Select an edge for direction</source>
+ <translation>Sélectionnez une arête pour la direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object</name>
+ <message>
+ <source>From face</source>
+ <translation>À l’angle</translation>
+ </message>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_offset</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Offset for "from" bounding plane</source>
+ <translation>Décalage pour "à partir" du plan englobant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_size</name>
+ <message>
+ <source>From size</source>
+ <translation>À partir de la taille</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object</name>
+ <message>
+ <source>To face</source>
+ <translation>Jusqu’à la face</translation>
+ </message>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_offset</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Offset for "to" bounding plane</source>
+ <translation>Décalage pour "au" plan englobant</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_size</name>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ <message>
+ <source>To size</source>
+ <translation>À la taille</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object</name>
+ <message>
+ <source><base normal></source>
+ <translation><base normale></translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:sketch</name>
+ <message>
+ <source>Select:<br /> 1. Planar face of non-sketch object or a plane. Sketch creation will be started.<br /> 2. An existing sketch face or contour. Extrusion will be filled by it.<br /> 3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it.</source>
+ <translation>Sélectionnez : <br /> 1. Face plane d'un objet non esquissé ou d'un plan. La création de l’esquisse sera lancée. <br /> 2. Une face ou un contour d’esquisse existant. L'extrusion sera remplie par elle. <br /> 3. Une forme de résultat existante de type: contours / arête / sommets. L'extrusion sera remplie par elle.</translation>
+ </message>
+ </context>
+
+ <!-- ExtrusionCut -->
+ <context>
+ <name>ExtrusionCut</name>
+ <message>
+ <source>ExtrusionCut</source>
+ <translation>Enlèvement de matière extrudé</translation>
+ </message>
+ <message>
+ <source>Cuts an extrusion from a solid</source>
+ <translation>Coupe une extrusion d'un solide</translation>
+ </message>
+ <message>
+ <source>Extrusion</source>
+ <translation>Extrusion</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:CreationMethod</name>
+ <message>
+ <source>By bounding faces and offsets</source>
+ <translation>En délimitant les faces et les décalages</translation>
+ </message>
+ <message>
+ <source>By sizes</source>
+ <translation>Par tailles</translation>
+ </message>
+ <message>
+ <source>Through all</source>
+ <translation>À travers tous</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base</name>
+ <message>
+ <source>Select a sketch face</source>
+ <translation>Sélectionnez une face d'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez une face d'esquisse.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object</name>
+ <message>
+ <source><base normal></source>
+ <translation><base normale></translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Direction</translation>
+ </message>
+ <message>
+ <source>Select an edge for direction</source>
+ <translation>Sélectionnez une arête pour la direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object</name>
+ <message>
+ <source>From face</source>
+ <translation>À l’angle</translation>
+ </message>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_offset</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Offset for bounding plane</source>
+ <translation>Décalage pour le plan englobant</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_size</name>
+ <message>
+ <source>From size</source>
+ <translation>À partir de la taille</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects</name>
+ <message>
+ <source>Cut from:</source>
+ <translation>Coupé de:</translation>
+ </message>
+ <message>
+ <source>Objects to Cut</source>
+ <translation>Objets à couper</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object</name>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ <message>
+ <source>To face</source>
+ <translation>Jusqu’à la face</translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_offset</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Offset for bounding plane</source>
+ <translation>Décalage pour le plan englobant</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_size</name>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ <message>
+ <source>To size</source>
+ <translation>À la taille</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:sketch</name>
+ <message>
+ <source>Select:<br /> 1. Planar face of non-sketch object or a plane. Sketch creation will be started.<br /> 2. An existing sketch face or contour. Extrusion will be filled by it.<br /> 3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it.</source>
+ <translation>Sélectionnez : <br /> 1. Face plane d'un objet non esquissé ou d'un plan. La création de l’esquisse sera lancée. <br /> 2. Une face ou un contour d’esquisse existant. L'extrusion sera remplie par elle. <br /> 3. Une forme de résultat existante de type: contours / arête / sommets. L'extrusion sera remplie par elle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object:FeaturesPlugin_ValidatorExtrusionBoundary</name>
+ <message>
+ <source>Error: Extrusion algorithm failed.</source>
+ <translation>Erreur : l'algorithme d'extrusion a échoué.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Les objets principaux ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object:FeaturesPlugin_ValidatorExtrusionBoundary</name>
+ <message>
+ <source>Error: Extrusion algorithm failed.</source>
+ <translation>Erreur : l'algorithme d'extrusion a échoué.</translation>
+ </message>
+ </context>
+
+ <!-- ExtrusionFuse -->
+ <context>
+ <name>ExtrusionFuse</name>
+ <message>
+ <source>ExtrusionFuse</source>
+ <translation>Bossage extrudé</translation>
+ </message>
+ <message>
+ <source>Fuses an extrusion with a solid</source>
+ <translation>Fusionne une extrusion avec un solide</translation>
+ </message>
+ <message>
+ <source>Extrusion</source>
+ <translation>Extrusion</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:CreationMethod</name>
+ <message>
+ <source>By bounding faces and offsets</source>
+ <translation>En délimitant les faces et les décalages</translation>
+ </message>
+ <message>
+ <source>By sizes</source>
+ <translation>Par tailles</translation>
+ </message>
+ <message>
+ <source>Through all</source>
+ <translation>À travers tous</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base</name>
+ <message>
+ <source>Select a sketch face</source>
+ <translation>Sélectionnez une face d'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object</name>
+ <message>
+ <source><base normal></source>
+ <translation><base normale></translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Direction</translation>
+ </message>
+ <message>
+ <source>Select an edge for direction</source>
+ <translation>Sélectionnez une arête pour la direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object</name>
+ <message>
+ <source>From face</source>
+ <translation>À l’angle</translation>
+ </message>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_offset</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Offset for bounding plane</source>
+ <translation>Décalage pour le plan englobant</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_size</name>
+ <message>
+ <source>From size</source>
+ <translation>À partir de la taille</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects</name>
+ <message>
+ <source>Fuse with:</source>
+ <translation>Fusionner avec:</translation>
+ </message>
+ <message>
+ <source>Objects to Fuse</source>
+ <translation>Objets à fusionner</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object</name>
+ <message>
+ <source>To face</source>
+ <translation>Jusqu’à la face</translation>
+ </message>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_offset</name>
+ <message>
+ <source>Offset</source>
+ <translation>Décalage</translation>
+ </message>
+ <message>
+ <source>Offset for bounding plane</source>
+ <translation>Décalage pour le plan englobant</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_size</name>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ <message>
+ <source>To size</source>
+ <translation>À la taille</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:sketch</name>
+ <message>
+ <source>Select:<br /> 1. Planar face of non-sketch object or a plane. Sketch creation will be started.<br /> 2. An existing sketch face or contour. Extrusion will be filled by it.<br /> 3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it.</source>
+ <translation>Sélectionnez : <br /> 1. Face plane d'un objet non esquissé ou d'un plan. La création de l’esquisse sera lancée. <br /> 2. Une face ou un contour d’esquisse existant. L'extrusion sera remplie par elle. <br /> 3. Une forme de résultat existante de type: contours / arête / sommets. L'extrusion sera remplie par elle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionner des objets de base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object:FeaturesPlugin_ValidatorExtrusionBoundary</name>
+ <message>
+ <source>Error: Extrusion algorithm failed.</source>
+ <translation>Erreur : l'algorithme d'extrusion a échoué.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Les objets principaux ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object:FeaturesPlugin_ValidatorExtrusionBoundary</name>
+ <message>
+ <source>Error: Extrusion algorithm failed.</source>
+ <translation>Erreur : l'algorithme d'extrusion a échoué.</translation>
+ </message>
+ </context>
+
+
+ <!-- Fillet -->
+ <context>
+ <name>Fillet</name>
+ <message>
+ <source>Fillet</source>
+ <translation>Congé</translation>
+ </message>
+ <message>
+ <source>Perform fillet on face or edge</source>
+ <translation>Effectuer un congé sur la face ou le bord</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fillet:creation_method</name>
+ <message>
+ <source>Fixed radius</source>
+ <translation>Rayon fixe</translation>
+ </message>
+ <message>
+ <source>Varying radius</source>
+ <translation>Rayon variable</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fillet:main_objects</name>
+ <message>
+ <source>Faces or/and edges</source>
+ <translation>Faces ou/et bords</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fillet:radius1</name>
+ <message>
+ <source>Fillet radius at start point.</source>
+ <translation>Rayon du congé au point de départ.</translation>
+ </message>
+ <message>
+ <source>Fillet radius.</source>
+ <translation>Rayon du congé.</translation>
+ </message>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ <message>
+ <source>Start radius</source>
+ <translation>Rayon de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fillet:radius2</name>
+ <message>
+ <source>End radius</source>
+ <translation>Rayon de fin</translation>
+ </message>
+ <message>
+ <source>Fillet radius at end point.</source>
+ <translation>Rayon du congé au point final.</translation>
+ </message>
+ </context>
+
+ <!-- Fuse -->
+ <context>
+ <name>Fuse</name>
+ <message>
+ <source>Fuse</source>
+ <translation>Fusionner</translation>
+ </message>
+ <message>
+ <source>Perform boolean fuse operation with objects</source>
+ <translation>Effectuer l’opération booléenne fusion avec des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fuse:FeaturesPlugin_ValidatorBooleanFuseArguments</name>
+ <message>
+ <source>Not enough arguments for Fuse operation.</source>
+ <translation>Pas assez d'arguments pour l'opération Fusionner.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fuse:creation_method</name>
+ <message>
+ <source>Simple</source>
+ <translation>Simple</translation>
+ </message>
+ <message>
+ <source>advanced</source>
+ <translation>avancée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fuse:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Objects</source>
+ <translation>Objets</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fuse:remove_intersection_edges</name>
+ <message>
+ <source>Remove intersection edges</source>
+ <translation>Supprimer les arêtes d'intersection</translation>
+ </message>
+ <message>
+ <source>Remove intersection edges if they laying on the same surface</source>
+ <translation>Supprimez les arêtes d'intersection si elles reposent sur la même surface</translation>
+ </message>
+ </context>
+ <context>
+ <name>Fuse:tool_objects</name>
+ <message>
+ <source>Select tools</source>
+ <translation>Sélectionnez des outils</translation>
+ </message>
+ <message>
+ <source>Tool objects</source>
+ <translation>Objets outils</translation>
+ </message>
+ </context>
+
+ <!-- FusionFaces -->
+ <context>
+ <name>FusionFaces</name>
+ <message>
+ <source>Fuse Faces</source>
+ <translation>Fusionner des faces</translation>
+ </message>
+ <message>
+ <source>Performs fusion of connected faces</source>
+ <translation>Effectue la fusion de faces connectées</translation>
+ </message>
+ </context>
+ <context>
+ <name>FusionFaces:base_shape</name>
+ <message>
+ <source>Select a shape to modify.</source>
+ <translation>Sélectionnez une forme à modifier.</translation>
+ </message>
+ <message>
+ <source>Shape:</source>
+ <translation>Forme:</translation>
+ </message>
+ </context>
+ <context>
+ <name>FusionFaces:base_shape:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Context is empty.</source>
+ <translation>Erreur : le contexte est vide.</translation>
+ </message>
+ </context>
+
+ <!-- Intersection -->
+ <context>
+ <name>Intersection</name>
+ <message>
+ <source>Intersect objects with tools</source>
+ <translation>Intersection d'objets avec des outils</translation>
+ </message>
+ <message>
+ <source>Intersection</source>
+ <translation>Section</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects</name>
+ <message>
+ <source>Objects</source>
+ <translation>Objets</translation>
+ </message>
+ <message>
+ <source>Select objects (compounds, compsolids, solids, shells, faces or edges)</source>
+ <translation>Sélectionner des objets (assemblages, solides composites, coques, faces ou arêtes)</translation>
+ </message>
+ </context>
+
+ <!-- Partition -->
+ <context>
+ <name>Partition</name>
+ <message>
+ <source>Partition</source>
+ <translation>Partition</translation>
+ </message>
+ <message>
+ <source>Perform partition operations with solids</source>
+ <translation>Effectuer des opérations de partition avec des solides</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Attribute "%1" should contain at least %2 items.</source>
+ <translation>Erreur : l'attribut "%1" doit contenir au moins %2 éléments.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:base_objects</name>
+ <message>
+ <source>Base objects:</source>
+ <translation>Objets de base:</translation>
+ </message>
+ <message>
+ <source>Select objects for partitioning.</source>
+ <translation>Sélectionner des objets pour le partitionnement.</translation>
+ </message>
+ </context>
+
+ <!-- Pipe -->
+ <context>
+ <name>Pipe</name>
+ <message>
+ <source>Generates extrusion along a path</source>
+ <translation>Génère une extrusion le long d'un chemin</translation>
+ </message>
+ <message>
+ <source>Pipe</source>
+ <translation>Tuyau</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects</name>
+ <message>
+ <source>Base objects:</source>
+ <translation>Objets de base:</translation>
+ </message>
+ <message>
+ <source>Select a base objects</source>
+ <translation>Sélectionnez un objet de base</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal</name>
+ <message>
+ <source>Bi-Normal:</source>
+ <translation>Bi-normal:</translation>
+ </message>
+ <message>
+ <source>Select an edge for Bi-Normal</source>
+ <translation>Sélectionnez une arête pour Bi-Normal</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:creation_method</name>
+ <message>
+ <source>Pipe by objects, path and Bi-Normal</source>
+ <translation>Tyau par objets, chemin et Bi-Normal</translation>
+ </message>
+ <message>
+ <source>Pipe by objects, path and locations</source>
+ <translation>Tuyau par objets, chemins et emplacements</translation>
+ </message>
+ <message>
+ <source>Simple pipe by objects and path</source>
+ <translation>Tuyau simple par objets et chemin</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:locations_objects</name>
+ <message>
+ <source>Locations:</source>
+ <translation>Emplacements:</translation>
+ </message>
+ <message>
+ <source>Select one or more vertices to specify the locations</source>
+ <translation>Sélectionnez un ou plusieurs sommets pour spécifier les emplacements</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:locations_objects:FeaturesPlugin_ValidatorPipeLocations</name>
+ <message>
+ <source>Error: Empty selection context.</source>
+ <translation>Erreur : contexte de sélection vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:path_object</name>
+ <message>
+ <source>Path object:</source>
+ <translation>Objet chemin:</translation>
+ </message>
+ <message>
+ <source>Select an edge or wire for path</source>
+ <translation>Sélectionnez une arête ou un contour pour le chemin</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionner des objets de base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le vecteur binormal n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:path_object</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez une arête ou un contour pour le chemin.</translation>
+ </message>
+ </context>
+
+ <!-- Recover -->
+ <context>
+ <name>Recover</name>
+ <message>
+ <source>Recover</source>
+ <translation>Récupérer</translation>
+ </message>
+ <message>
+ <source>Visualize concealed objects</source>
+ <translation>Visualiser les objets cachés</translation>
+ </message>
+ </context>
+ <context>
+ <name>Recover:base_feature</name>
+ <message>
+ <source>Feature:</source>
+ <translation>Fonctionnalité:</translation>
+ </message>
+ <message>
+ <source>Select a feature that conceals results.</source>
+ <translation>Sélectionnez une fonctionnalité qui cache les résultats.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Recover:base_feature:FeaturesPlugin_ValidatorConcealedResult</name>
+ <message>
+ <source>Error: Empty feature.</source>
+ <translation>Erreur : fonction vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Recover:method</name>
+ <message>
+ <source>Concealed compounds</source>
+ <translation>Assemblages cachés</translation>
+ </message>
+ <message>
+ <source>Concealed results</source>
+ <translation>Résultats cachés</translation>
+ </message>
+ </context>
+
+ <!-- Remove_SubShapes -->
+ <context>
+ <name>Remove_SubShapes</name>
+ <message>
+ <source>Allows to remove sub-shapes from wires, shells, compsolids and compounds</source>
+ <translation>Permet de supprimer les sous formes de fils, coques, solides composites et assemblages</translation>
+ </message>
+ <message>
+ <source>Remove Sub-Shapes</source>
+ <translation>Supprimer les sous-formes</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape</name>
+ <message>
+ <source>Select a shape to modify.</source>
+ <translation>Sélectionnez une forme à modifier.</translation>
+ </message>
+ <message>
+ <source>Shape:</source>
+ <translation>Forme:</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:creation_method</name>
+ <message>
+ <source>By keeping sub-shapes</source>
+ <translation>En gardant les sous-formes</translation>
+ </message>
+ <message>
+ <source>By removing sub-shapes</source>
+ <translation>En supprimant les sous-formes</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes_to_keep</name>
+ <message>
+ <source>Select shapes to keep.</source>
+ <translation>Sélectionnez des formes à conserver.</translation>
+ </message>
+ <message>
+ <source>Sub-Shapes to keep:</source>
+ <translation>Sous-formes à garder:</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes_to_keep:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes_to_remove</name>
+ <message>
+ <source>Select shapes to remove.</source>
+ <translation>Sélectionnez les formes à supprimer.</translation>
+ </message>
+ <message>
+ <source>Sub-Shapes to remove:</source>
+ <translation>Sous-formes à supprimer:</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes_to_remove:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+
+ <!-- Revolution -->
+ <context>
+ <name>Revolution</name>
+ <message>
+ <source>Create a solid by revolution of a face</source>
+ <translation>Créer un solide par révolution d'une face</translation>
+ </message>
+ <message>
+ <source>Revolution</source>
+ <translation>Révolution</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:CreationMethod</name>
+ <message>
+ <source>By angles</source>
+ <translation>Par angles</translation>
+ </message>
+ <message>
+ <source>By bounding planes and angles</source>
+ <translation>En délimitant des plans et des angles</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for axis</source>
+ <translation>Sélectionnez une arête pour l'axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base</name>
+ <message>
+ <source>Base objects:</source>
+ <translation>Objets de base:</translation>
+ </message>
+ <message>
+ <source>Select a base objects</source>
+ <translation>Sélectionnez un objet de base</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>From angle</source>
+ <translation>De l'angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_object</name>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_offset</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for "from" bounding plane</source>
+ <translation>Angle pour "à partir du" plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>To angle</source>
+ <translation>Jusqu’à l’angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object</name>
+ <message>
+ <source><base sketch></source>
+ <translation><esquisse de base></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_offset</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for "to" bounding plane</source>
+ <translation>Angle pour "à" plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:sketch</name>
+ <message>
+ <source>Select:<br /> 1. Planar face of non-sketch object or a plane. Sketch creation will be started.<br /> 2. An existing sketch face or contour. Extrusion will be filled by it.<br /> 3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it.</source>
+ <translation>Sélectionnez : <br /> 1. Face plane d'un objet non esquissé ou d'un plan. La création de l’esquisse sera lancée. <br /> 2. Une face ou un contour d’esquisse existant. L'extrusion sera remplie par elle. <br /> 3. Une forme de résultat existante de type: contours / arête / sommets. L'extrusion sera remplie par elle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné</translation>
+ </message>
+ </context>
+
+ <!-- RevolutionCut -->
+ <context>
+ <name>RevolutionCut</name>
+ <message>
+ <source>RevolutionCut</source>
+ <translation>Enlèvement de matière avec révolution</translation>
+ </message>
+ <message>
+ <source>Cuts a revolution from a solid</source>
+ <translation>Coupe une révolution d'un solide</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>Revolution</source>
+ <translation>Révolution</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:CreationMethod</name>
+ <message>
+ <source>By angles</source>
+ <translation>Par angles</translation>
+ </message>
+ <message>
+ <source>By bounding planes and angles</source>
+ <translation>En délimitant des plans et des angles</translation>
+ </message>
+ <message>
+ <source>Through all</source>
+ <translation>À travers tous</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for axis</source>
+ <translation>Sélectionnez une arête pour l'axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base</name>
+ <message>
+ <source>Select a sketch face</source>
+ <translation>Sélectionnez une face d'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>From angle</source>
+ <translation>De l'angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_object</name>
+ <message>
+ <source><sketch></source>
+ <translation><esquisse></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_offset</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for "from" bounding plane</source>
+ <translation>Angle pour "à partir du" plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects</name>
+ <message>
+ <source>Cut from:</source>
+ <translation>Coupé de:</translation>
+ </message>
+ <message>
+ <source>Objects to Cut</source>
+ <translation>Objets à couper</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>To angle</source>
+ <translation>Jusqu’à l’angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_object</name>
+ <message>
+ <source><sketch></source>
+ <translation><esquisse></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_offset</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for "to" bounding plane</source>
+ <translation>Angle pour "à" plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:sketch</name>
+ <message>
+ <source>Select:<br /> 1. Planar face of non-sketch object or a plane. Sketch creation will be started.<br /> 2. An existing sketch face or contour. Extrusion will be filled by it.<br /> 3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it.</source>
+ <translation>Sélectionnez : <br /> 1. Face plane d'un objet non esquissé ou d'un plan. La création de l’esquisse sera lancée. <br /> 2. Une face ou un contour d’esquisse existant. L'extrusion sera remplie par elle. <br /> 3. Une forme de résultat existante de type: contours / arête / sommets. L'extrusion sera remplie par elle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Les objets principaux ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+
+ <!-- RevolutionFuse -->
+ <context>
+ <name>RevolutionFuse</name>
+ <message>
+ <source>RevolutionFuse</source>
+ <translation>Bossage avec révolution</translation>
+ </message>
+ <message>
+ <source>Fuses a revolution with a solid</source>
+ <translation>Fusionne une révolution avec un solide</translation>
+ </message>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>Revolution</source>
+ <translation>Révolution</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:CreationMethod</name>
+ <message>
+ <source>By angles</source>
+ <translation>Par angles</translation>
+ </message>
+ <message>
+ <source>By bounding planes and angles</source>
+ <translation>En délimitant des plans et des angles</translation>
+ </message>
+ <message>
+ <source>Through all</source>
+ <translation>À travers tous</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for axis</source>
+ <translation>Sélectionnez une arête pour l'axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base</name>
+ <message>
+ <source>Select a sketch face</source>
+ <translation>Sélectionnez une face d'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>From angle</source>
+ <translation>De l'angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_object</name>
+ <message>
+ <source><sketch></source>
+ <translation><esquisse></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_offset</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for "from" bounding plane</source>
+ <translation>Angle pour "à partir du" plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects</name>
+ <message>
+ <source>Fuse with:</source>
+ <translation>Fusionner avec:</translation>
+ </message>
+ <message>
+ <source>Objects to Fuse</source>
+ <translation>Objets à fusionner</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>To angle</source>
+ <translation>Jusqu’à l’angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_object</name>
+ <message>
+ <source><sketch></source>
+ <translation><esquisse></translation>
+ </message>
+ <message>
+ <source>Bounding plane (select a planar face)</source>
+ <translation>Plan englobant (sélectionnez une face plane)</translation>
+ </message>
+ <message>
+ <source>Plane face</source>
+ <translation>Face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_offset</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angle for "to" bounding plane</source>
+ <translation>Angle pour "à" plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:sketch</name>
+ <message>
+ <source>Select:<br /> 1. Planar face of non-sketch object or a plane. Sketch creation will be started.<br /> 2. An existing sketch face or contour. Extrusion will be filled by it.<br /> 3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it.</source>
+ <translation>Sélectionnez : <br /> 1. Face plane d'un objet non esquissé ou d'un plan. La création de l’esquisse sera lancée. <br /> 2. Une face ou un contour d’esquisse existant. L'extrusion sera remplie par elle. <br /> 3. Une forme de résultat existante de type: contours / arête / sommets. L'extrusion sera remplie par elle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Les objets principaux ne sont pas sélectionnés</translation>
+ </message>
+ </context>
+
+ <!-- Scale -->
+ <context>
+ <name>Scale</name>
+ <message>
+ <source>Perform scale objects</source>
+ <translation>Effectuer un changement d’échelle des objets</translation>
+ </message>
+ <message>
+ <source>Scale</source>
+ <translation>Échelle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:CreationMethod</name>
+ <message>
+ <source>By one common factor for the three directions</source>
+ <translation>Par un facteur commun aux trois directions</translation>
+ </message>
+ <message>
+ <source>Different factors for the three directions</source>
+ <translation>Différents facteurs pour les trois directions</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:center_point</name>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ <message>
+ <source>Select the center point</source>
+ <translation>Sélectionnez le point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:scale_factor</name>
+ <message>
+ <source>Scale factor</source>
+ <translation>Facteur d'échelle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:scale_factor_x</name>
+ <message>
+ <source>Scale factor in X</source>
+ <translation>Facteur d'échelle suivant X</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:scale_factor_y</name>
+ <message>
+ <source>Scale factor in Y</source>
+ <translation>Facteur d'échelle suivant Y</translation>
+ </message>
+ </context>
+ <context>
+ <name>Scale:scale_factor_z</name>
+ <message>
+ <source>Scale factor in Z</source>
+ <translation>Facteur d'échelle suivant Z</translation>
+ </message>
+ </context>
+
+ <!-- Smash -->
+ <context>
+ <name>Smash</name>
+ <message>
+ <source>Perform boolean smash operation with objects</source>
+ <translation>Effectuer l’opération booléenne smash avec des objets</translation>
+ </message>
+ <message>
+ <source>Smash</source>
+ <translation>Smash</translation>
+ </message>
+ </context>
+ <context>
+ <name>Smash:FeaturesPlugin_ValidatorBooleanArguments</name>
+ <message>
+ <source>Objects not selected.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Smash:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Smash:tool_objects</name>
+ <message>
+ <source>Select tools</source>
+ <translation>Sélectionnez des outils</translation>
+ </message>
+ <message>
+ <source>Tool objects</source>
+ <translation>Objets outils</translation>
+ </message>
+ </context>
+ <context>
+ <name>Smash:FeaturesPlugin_ValidatorBooleanArguments</name>
+ <message>
+ <source>Tools not selected.</source>
+ <translation>Les objets outils ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+
+ <!-- Split -->
+ <context>
+ <name>Split</name>
+ <message>
+ <source>Perform boolean split operation with objects</source>
+ <translation>Effectuer l’opération booléenne division avec des objets</translation>
+ </message>
+ <message>
+ <source>Split</source>
+ <translation>Diviser</translation>
+ </message>
+ </context>
+ <context>
+ <name>Split:FeaturesPlugin_ValidatorBooleanArguments</name>
+ <message>
+ <source>Objects not selected.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Split:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Split:tool_objects</name>
+ <message>
+ <source>Select tools</source>
+ <translation>Sélectionnez des outils</translation>
+ </message>
+ <message>
+ <source>Tool objects</source>
+ <translation>Objets outils</translation>
+ </message>
+ </context>
+
+ <!-- Union -->
+ <context>
+ <name>Union</name>
+ <message>
+ <source>Perform union operations with shapes</source>
+ <translation>Effectuer des opérations réunion avec des formes</translation>
+ </message>
+ <message>
+ <source>Union</source>
+ <translation>Réunion</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:base_objects</name>
+ <message>
+ <source>Base objects:</source>
+ <translation>Objets de base:</translation>
+ </message>
+ <message>
+ <source>Select solids for union.</source>
+ <translation>Sélectionner les solides pour la réunion.</translation>
+ </message>
+ </context>
+
+ <!-- Validators -->
+
+ <context>
+ <name>Scale:center_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'objet de base pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToSize = -FromSize.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Validator should be used with 2 parameters for extrusion.</source>
+ <translation>Validateur "FeaturesPlugin_ValidatorExtrusionDir" doit être utilisé avec 2 paramètres d'extrusion.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Direction is parallel to one of the selected face or face on selected shell.</source>
+ <translation>La direction est parallèle à l'une des faces sélectionnées ou à la face de la coque sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "sketch" is not initialized.</source>
+ <translation>L'objet de base pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base" is not initialized.</source>
+ <translation>L'objet de base pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "direction_object" is not initialized.</source>
+ <translation>L'objet Direction pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_object" is not initialized.</source>
+ <translation>L’objet de départ pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_object" is not initialized.</source>
+ <translation>L’objet destination de l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: The attribute with the %1 type is not processed</source>
+ <translation>Erreur : l'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: Wrong parameters in XML definition for %1 type</source>
+ <translation>Erreur : paramètres incorrects dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Wrong parameters in XML definition for %1 type</source>
+ <translation>Mauvais paramètres dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Le type d’une forme sélectionnée n’est pas acceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Erreur : attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute have empty context.</source>
+ <translation>Erreur : l'attribut a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Objet de direction non sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Objet de direction non sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Objet de direction non sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Nombre incorrect d'arguments de validation dans XML (9 prévus).</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToSize = -FromSize.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Base objects list contains vertex or edge, so attribute "direction_object" can not be used with default value. Select direction for extrusion.</source>
+ <translation>La liste des objets de base contient un sommet ou une arête, ainsi la direction par défaut ne peut pas être utilisée. Sélectionnez la direction d'extrusion.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object:FeaturesPlugin_ValidatorExtrusionBoundary</name>
+ <message>
+ <source>Error: Extrusion algorithm failed.</source>
+ <translation>Erreur : l'algorithme d'extrusion a échoué.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object:FeaturesPlugin_ValidatorExtrusionBoundary</name>
+ <message>
+ <source>Error: Extrusion algorithm failed.</source>
+ <translation>Erreur : l'algorithme d'extrusion a échoué.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source> Attribute "base" is not initialized.</source>
+ <translation>L'objet de base pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: </source>
+ <translation>Les objets sélectionnés contiennent un élément avec un type de forme non autorisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Validator should be used with 2 parameters for extrusion.</source>
+ <translation>Validateur "FeaturesPlugin_ValidatorExtrusionDir" doit être utilisé avec 2 paramètres d'extrusion.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Direction is parallel to one of the selected face or face on selected shell.</source>
+ <translation>La direction est parallèle à l'une des faces sélectionnées ou à la face de la coque sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "sketch" is not initialized.</source>
+ <translation>L'objet de base pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "direction_object" is not initialized.</source>
+ <translation>L'objet Direction pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_object" is not initialized.</source>
+ <translation>L’objet de départ pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_object" is not initialized.</source>
+ <translation>L’objet destination de l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_offset" is not initialized.</source>
+ <translation>Entrez le décalage "jusqu’à".</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Les objets à couper ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: The attribute with the %1 type is not processed</source>
+ <translation>Erreur : l'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: Wrong parameters in XML definition for %1 type</source>
+ <translation>Erreur : paramètres incorrects dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Wrong parameters in XML definition for %1 type</source>
+ <translation>Mauvais paramètres dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Le type d’une forme sélectionnée n’est pas acceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Sélectionner des objets de base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut</name>
+ <message>
+ <source>base - FeaturesPlugin_ValidatorBaseForGeneration: Error: Attribute have empty context.</source>
+ <translation>L'objet sélectionné est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Nombre incorrect d'arguments de validation dans XML (9 prévus).</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToSize = -FromSize.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Nombre incorrect d'arguments du validateur "GeomValidators_ZeroOffset" en XML (9 attendus).</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToAngle = -FromAngle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "sketch" is not initialized.</source>
+ <translation>L'objet de base pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base" is not initialized.</source>
+ <translation>L'objet de base pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_object" is not initialized.</source>
+ <translation>L'objet de départ pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_object" is not initialized.</source>
+ <translation>L’objet destination de la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: The attribute with the %1 type is not processed</source>
+ <translation>Erreur : l'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: Wrong parameters in XML definition for %1 type</source>
+ <translation>Erreur : paramètres incorrects dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Wrong parameters in XML definition for %1 type</source>
+ <translation>Mauvais paramètres dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Le type d’une forme sélectionnée n’est pas acceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Erreur : attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute have empty context.</source>
+ <translation>Erreur : l'attribut a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromAngle = -ToAngle et les plans englobants coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: </source>
+ <translation>Les objets sélectionnés contiennent un élément avec un type de forme non autorisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Nombre incorrect d'arguments du validateur "GeomValidators_ZeroOffset" en XML (9 attendus).</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToAngle = -FromAngle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "sketch" is not initialized.</source>
+ <translation>L'objet de base pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base" is not initialized.</source>
+ <translation>L'objet de base pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_object" is not initialized.</source>
+ <translation>L'objet de départ pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_object" is not initialized.</source>
+ <translation>L’objet destination de la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>L’objet à couper n’est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: The attribute with the %1 type is not processed</source>
+ <translation>Erreur : l'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: Wrong parameters in XML definition for %1 type</source>
+ <translation>Erreur : paramètres incorrects dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Wrong parameters in XML definition for %1 type</source>
+ <translation>Mauvais paramètres dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Le type d’une forme sélectionnée n’est pas acceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Erreur : attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute have empty context.</source>
+ <translation>Erreur : l'attribut a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base" is not initialized.</source>
+ <translation>Les objets de base pour l'extrusion ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: </source>
+ <translation>Les objets sélectionnés contiennent un élément avec un type de forme non autorisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Validator should be used with 2 parameters for extrusion.</source>
+ <translation>Validateur "FeaturesPlugin_ValidatorExtrusionDir" doit être utilisé avec 2 paramètres d'extrusion.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:FeaturesPlugin_ValidatorExtrusionDir</name>
+ <message>
+ <source>Error: Direction is parallel to one of the selected face or face on selected shell.</source>
+ <translation>La direction est parallèle à l'une des faces sélectionnées ou à la face de la coque sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "sketch" is not initialized.</source>
+ <translation>L'objet de base pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base" is not initialized.</source>
+ <translation>Les objets de base pour l'extrusion ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "direction_object" is not initialized.</source>
+ <translation>L'objet Direction pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_object" is not initialized.</source>
+ <translation>L’objet de départ pour l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_object" is not initialized.</source>
+ <translation>L’objet destination de l'extrusion n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Les objets à fusionner ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: The attribute with the %1 type is not processed</source>
+ <translation>Erreur : l'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: Wrong parameters in XML definition for %1 type</source>
+ <translation>Erreur : paramètres incorrects dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Wrong parameters in XML definition for %1 type</source>
+ <translation>Mauvais paramètres dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Le type d’une forme sélectionnée n’est pas acceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Erreur : attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute have empty context.</source>
+ <translation>Erreur : l'attribut a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:direction_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Nombre incorrect d'arguments de validation dans XML (9 prévus).</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToSize = -FromSize.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromSize = -ToSize et les plans de délimitation coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>FromSize = -ToSize and bounding planes are coincident.</source>
+ <translation>FromAngle = -ToAngle et les plans englobants coïncident.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: </source>
+ <translation>Les objets sélectionnés contiennent un élément avec un type de forme non autorisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'objet n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Nombre incorrect d'arguments du validateur "GeomValidators_ZeroOffset" en XML (9 attendus).</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>ToSize = -FromSize.</source>
+ <translation>ToAngle = -FromAngle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>From face selection is invalid.</source>
+ <translation>La face de départ sélectionnée est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:GeomValidators_ZeroOffset</name>
+ <message>
+ <source>To face selection is invalid.</source>
+ <translation>La sélection de la face finale est invalide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "sketch" is not initialized.</source>
+ <translation>L'objet de base pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base" is not initialized.</source>
+ <translation>L'objet de base pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_object" is not initialized.</source>
+ <translation>L'objet de départ pour la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_object" is not initialized.</source>
+ <translation>L’objet destination de la révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Les objets à fusionner ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: The attribute with the %1 type is not processed</source>
+ <translation>Erreur : l'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Error: Wrong parameters in XML definition for %1 type</source>
+ <translation>Erreur : paramètres incorrects dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:sketch:FeaturesPlugin_ValidatorCompositeLauncher</name>
+ <message>
+ <source>Wrong parameters in XML definition for %1 type</source>
+ <translation>Mauvais paramètres dans la définition XML pour le type %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Le type d’une forme sélectionnée n’est pas acceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Erreur : attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute have empty context.</source>
+ <translation>Erreur : l'attribut a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de révolution n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>La forme n'est pas un cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>La forme n'est pas une face disponible.</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:main_objects:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean</name>
+ <message>
+ <source>Boolean</source>
+ <translation>Booléen</translation>
+ </message>
+ <message>
+ <source>Boolean operations with objects</source>
+ <translation>Opérations booléennes avec des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:bool_type</name>
+ <message>
+ <source>Operation type</source>
+ <translation>Type d'opération</translation>
+ </message>
+ <message>
+ <source>Type of boolean operation</source>
+ <translation>Type d'opération booléenne</translation>
+ </message>
+ <message>
+ <source>Cut</source>
+ <translation>Découpe</translation>
+ </message>
+ <message>
+ <source>Fuse</source>
+ <translation>Fusionner</translation>
+ </message>
+ <message>
+ <source>Common</source>
+ <translation>Intersection</translation>
+ </message>
+ <message>
+ <source>Fill</source>
+ <translation>Remplir</translation>
+ </message>
+ <message>
+ <source>Smash</source>
+ <translation>Smash</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:main_objects:FeaturesPlugin_ValidatorBooleanSelection</name>
+ <message>
+ <source>Error: Empty attribute selection.</source>
+ <translation>Sélectionner des objets.</translation>
+ </message>
+ <message>
+ <source>Error: Empty selection context.</source>
+ <translation>Objet sélectionné invalide.</translation>
+ </message>
+ <message>
+ <source>Error: Result construction not allowed for selection.</source>
+ <translation>Résultat de construction non autorisé pour la sélection.</translation>
+ </message>
+ <message>
+ <source>Error: Empty shape.</source>
+ <translation>Objet sélectionné invalide.</translation>
+ </message>
+ <message>
+ <source>Error: Local selection not allowed.</source>
+ <translation>Sélection locale non autorisée.</translation>
+ </message>
+ <message>
+ <source>Error: Selected shape has the wrong type.</source>
+ <translation>La forme sélectionnée est du mauvais type.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:tool_objects</name>
+ <message>
+ <source>Tool objects</source>
+ <translation>Objets outils</translation>
+ </message>
+ <message>
+ <source>Select tools</source>
+ <translation>Sélectionnez des outils</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:tool_objects:FeaturesPlugin_ValidatorBooleanSelection</name>
+ <message>
+ <source>Error: Empty attribute selection.</source>
+ <translation>Sélectionnez des outils.</translation>
+ </message>
+ <message>
+ <source>Error: Empty selection context.</source>
+ <translation>Outil sélectionné non valide.</translation>
+ </message>
+ <message>
+ <source>Error: Result construction not allowed for selection.</source>
+ <translation>Résultat de construction non autorisé pour la sélection.</translation>
+ </message>
+ <message>
+ <source>Error: Empty shape.</source>
+ <translation>Outil sélectionné non valide.</translation>
+ </message>
+ <message>
+ <source>Error: Local selection not allowed.</source>
+ <translation>Sélection locale non autorisée.</translation>
+ </message>
+ <message>
+ <source>Error: Selected shape has the wrong type.</source>
+ <translation>La forme sélectionnée est du mauvais type.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:GeomValidators_BooleanArguments</name>
+ <message>
+ <source>Not enough arguments</source>
+ <translation>Pas assez d'arguments.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Boolean:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "bool_type" is not initialized.</source>
+ <translation>Sélectionnez le type d'opération.</translation>
+ </message>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Sélectionner des objets.</translation>
+ </message>
+ <message>
+ <source>Attribute "tool_objects" is not initialized.</source>
+ <translation>Sélectionnez des outils.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Attribute \"%1\" should contain at least %2 items.</source>
+ <translation>Au moins %2 objets doivent être sélectionnés dans "%1"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Wrong number of arguments (expected 2): selection list id and min number of objects</source>
+ <translation>Nombre incorrect de validateurs "GeomValidators_MinObjectsSelected" (2 attendus) : id de la liste de sélection et nombre minimal d'objets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Could not get attribute \"%1\".</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:base_objects:FeaturesPlugin_ValidatorPartitionSelection</name>
+ <message>
+ <source>Error: This validator can only work with selection list in \"Partition\" feature.</source>
+ <translation>Erreur : ce validateur ne peut fonctionner qu'avec une liste de sélection dans la fonctionnalité \"Partition\".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:base_objects:FeaturesPlugin_ValidatorPartitionSelection</name>
+ <message>
+ <source>Error: Only body shapes and construction planes are allowed for selection.</source>
+ <translation>Seuls les formes et les plans de construction sont autorisés pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Partition:base_objects:FeaturesPlugin_ValidatorPartitionSelection</name>
+ <message>
+ <source>Error: Only body shapes and construction planes are allowed for selection.</source>
+ <translation>Seuls les formes et les plans de construction sont autorisés pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>L'objet de base pour le tuyau n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "binormal" is not initialized.</source>
+ <translation>Le vecteur binormal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "path_object" is not initialized.</source>
+ <translation>L'objet pour le chemin de canal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le vecteur binormal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:path_object:FeaturesPlugin_ValidatorPipePath</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>L'objet pour le chemin de canal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:FeaturesPlugin_ValidatorPipeLocations</name>
+ <message>
+ <source>Error: Could not get \"%1\" attribute.</source>
+ <translation>Impossible d'obtenir l'attribut " %1"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:FeaturesPlugin_ValidatorPipeLocations</name>
+ <message>
+ <source>Error: Number of locations should be the same as base objects.</source>
+ <translation>Le nombre d'emplacements doit être identique à celui des objets de base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>L'objet de base pour le tuyau n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "path_object" is not initialized.</source>
+ <translation>L'objet pour le chemin de canal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "binormal" is not initialized.</source>
+ <translation>Le vecteur binormal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "locations_objects" is not initialized.</source>
+ <translation>Emplacements non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Validator parameters is empty.</source>
+ <translation>Erreur : les paramètres du validateur sont vides.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute contains unacceptable shape.</source>
+ <translation>Erreur : l'attribut contient une forme inacceptable.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>Erreur : contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Compound should contain only faces, edges or vertices.</source>
+ <translation>L’assemblage doit contenir uniquement des faces, des arêtes ou des sommets.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Object from this sketch is already selected. Sketch is not allowed for selection.</source>
+ <translation>L'objet de cette esquisse est déjà sélectionné. L'esquisse n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Whole sketch with this object is already selected. Don't allow to select this object.</source>
+ <translation>L'esquisse entière avec cet objet est déjà sélectionnée. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Wire with wrong orientation selected.</source>
+ <translation>Contour avec mauvaise orientation sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Les objets de ce contour sont déjà sélectionnés. Ne pas autoriser à sélectionner cet objet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty attribute.</source>
+ <translation>Erreur : attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Attribute have empty context.</source>
+ <translation>Erreur : l'attribut a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Empty shape selected</source>
+ <translation>Erreur : forme vide sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Infinite constructions is not allowed as base.</source>
+ <translation>Les constructions infinies ne sont pas autorisées comme base.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape is in the local selection. Only global selection is allowed.</source>
+ <translation>La forme sélectionnée est dans la sélection locale. Seule la sélection globale est autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
+ <message>
+ <source>Error: Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, whole sketch (if it has at least one face), and whole objects with shape types: %1</source>
+ <translation>Le type de la forme sélectionnée n’est pas autorisé. Les types acceptables sont les suivants: faces ou contours sur l'esquisse, esquisse entière (si elle possède au moins une face) et objets entiers des types de forme: %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:path_object:FeaturesPlugin_ValidatorPipePath</name>
+ <message>
+ <source>Error: This validator can only work with path selector in \"Pipe\" feature.</source>
+ <translation>Erreur : ce validateur ne peut fonctionner qu'avec le sélecteur de chemin dans la fonctionnalité \"Tuyau\".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:path_object:FeaturesPlugin_ValidatorPipePath</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>L'objet pour le chemin de canal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:path_object:FeaturesPlugin_ValidatorPipePath</name>
+ <message>
+ <source>Error: Local selection of wires not allowed.</source>
+ <translation>Sélection locale des contours non autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le vecteur binormal n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Pipe:binormal:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:FeaturesPlugin_ValidatorRemoveSubShapesResult</name>
+ <message>
+ <source>Error: Base shape is empty.</source>
+ <translation>La forme de base n'est pas sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Context is empty.</source>
+ <translation>L'objet sélectionné a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>L'objet sélectionné a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:FeaturesPlugin_ValidatorRemoveSubShapesResult</name>
+ <message>
+ <source>Error: Could not get \"%1\" attribute.</source>
+ <translation>Impossible d'obtenir l'attribut " %1".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:FeaturesPlugin_ValidatorRemoveSubShapesResult</name>
+ <message>
+ <source>Error: Base shape is empty.</source>
+ <translation>La forme de base n'est pas sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:FeaturesPlugin_ValidatorRemoveSubShapesResult</name>
+ <message>
+ <source>Error: Resulting shape is not valid.</source>
+ <translation>La forme résultante n'est pas valide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_shape" is not initialized.</source>
+ <translation>La forme de base n'est pas sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "subshapes" is not initialized.</source>
+ <translation>Les sous-formes ne sont pas sélectionnées.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La forme est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Context is empty.</source>
+ <translation>L'objet sélectionné a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:base_shape:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Result construction selected.</source>
+ <translation>Erreur : construction du résultat sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.</source>
+ <translation>Erreur : ce validateur ne peut fonctionner qu'avec la liste de sélection de la fonction \"Supprimer les sous-formes\".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Could not get \"%1\" attribute.</source>
+ <translation>Erreur : impossible d'obtenir l'attribut \"%1\".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Empty context.</source>
+ <translation>L'objet sélectionné a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Empty base shape.</source>
+ <translation>Forme de base non sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
+ <message>
+ <source>Error: Only sub-shapes of selected shape is allowed for selection.</source>
+ <translation>Seules les sous-formes de la forme sélectionnée sont autorisées pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Les objets principaux ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "tool_objects" is not initialized.</source>
+ <translation>Les objets outils ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty selection.</source>
+ <translation>Sélection vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty attribute selection.</source>
+ <translation>La sélection d'attribut est vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty selection context.</source>
+ <translation>L'objet sélectionné a un contexte vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty feature.</source>
+ <translation>Les objets sélectionnés ont une fonctionnalité vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: %1 shape is not allowed for selection.</source>
+ <translation>La forme %1 n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty shape.</source>
+ <translation>Forme vide sélectionnée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: selected shape has the wrong type.</source>
+ <translation>La forme sélectionnée est du mauvais type.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Les objets principaux ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "tool_objects" is not initialized.</source>
+ <translation>Les objets outils ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty selection.</source>
+ <translation>Erreur : sélection vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty attribute selection.</source>
+ <translation>Erreur : sélection d'attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty selection context.</source>
+ <translation>Erreur : contexte de sélection vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty feature.</source>
+ <translation>Erreur : fonctionnalité vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: %1 shape is not allowed for selection.</source>
+ <translation>La forme %1 n'est pas autorisée pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: empty shape.</source>
+ <translation>Erreur : forme vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: Local selection not allowed.</source>
+ <translation>Sélection locale non autorisée.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Intersection:main_objects:GeomValidators_IntersectionSelection</name>
+ <message>
+ <source>Error: selected shape has the wrong type.</source>
+ <translation>La forme sélectionnée est du mauvais type.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "placement_end_shape" is not initialized.</source>
+ <translation>La forme du placement final n'est pas définie.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_end_shape:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one shape in placement_end_shape and placement_start_shape attributes.</source>
+ <translation>Les formes de placement de début et de fin sont les mêmes.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "placement_objects_list" is not initialized.</source>
+ <translation>Les objets à placer ne sont pas sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_objects_list:FeaturesPlugin_ValidatorTransform</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_objects_list:FeaturesPlugin_ValidatorTransform</name>
+ <message>
+ <source>Objects from the %1 group can be selected in the %2 document, but an objects from the %3 group is selected.</source>
+ <translation>Les objets du groupe %1 peuvent être sélectionnés dans le document %2, mais un objet du groupe %3 est sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "placement_start_shape" is not initialized.</source>
+ <translation>La forme de départ n'est pas définie.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "angle" is not initialized.</source>
+ <translation>L'angle n'est pas défini.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de rotation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de rotation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Les objets sélectionnés contiennent un élément avec un type de forme non autorisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de rotation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'axe de rotation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'axe de rotation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de rotation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "angle" is not initialized.</source>
+ <translation>L'angle n'est pas défini.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:main_objects:FeaturesPlugin_ValidatorTransform</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:main_objects:FeaturesPlugin_ValidatorTransform</name>
+ <message>
+ <source>Objects from the %1 group can be selected in the %2 document, but an objects from the %3 group is selected.</source>
+ <translation>Les objets du groupe %1 peuvent être sélectionnés dans le document %2, mais un objet du groupe %3 est sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>L'axe de translation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'axe de translation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Il ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Il fait référence à un attribut vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is \"%1\", it should be \"%2\"</source>
+ <translation>Le type de forme est "%1", il devrait être "%2".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'axe de translation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'axe de translation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'axe de translation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:main_objects:FeaturesPlugin_ValidatorTransform</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:main_objects:FeaturesPlugin_ValidatorTransform</name>
+ <message>
+ <source>Objects from the %1 group can be selected in the %2 document, but an objects from the %3 group is selected.</source>
+ <translation>Les objets du groupe %1 peuvent être sélectionnés dans le document %2, mais un objet du groupe %3 est sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:FeaturesPlugin_ValidatorUnionArguments</name>
+ <message>
+ <source>Error: Could not get \"%1\" attribute.</source>
+ <translation>Impossible d'obtenir l'attribut " %1".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:FeaturesPlugin_ValidatorUnionArguments</name>
+ <message>
+ <source>Error: Not all shapes have shared topology.</source>
+ <translation>La topologie n'est pas partagée par toutes les formes.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_objects" is not initialized.</source>
+ <translation>Objets non sélectionnés.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:base_objects:FeaturesPlugin_ValidatorUnionSelection</name>
+ <message>
+ <source>Error: This validator can only work with selection list in \"%1\" feature.</source>
+ <translation>Erreur : ce validateur ne peut fonctionner qu'avec la liste de sélection dans la fonctionnalité \"%1\".</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:base_objects:FeaturesPlugin_ValidatorUnionSelection</name>
+ <message>
+ <source>Error: Whole compsolids not allowed for selection.</source>
+ <translation>Solides composites entiers non autorisés pour la sélection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Wrong number of arguments (expected 2): selection list id and min number of objects</source>
+ <translation>Erreur : Nombre d'arguments incorrect (2 attendus): id de la liste de sélection et nombre minimal d'objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>Union:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Could not get attribute \"%1\".</source>
+ <translation>Erreur : impossible d'obtenir l'attribut \"%1\".</translation>
+ </message>
+ </context>
+ <context>
+ <name>FusionFaces:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "base_shape" is not initialized.</source>
+ <translation>La forme de base n'est pas sélectionnée.</translation>
+ </message>
+ </context>
+
+ <!-- Part menu -->
+
+ <!-- AngularCopy -->
+ <context>
+ <name>AngularCopy</name>
+ <message>
+ <source>Angular Copy</source>
+ <translation>Copie angulaire</translation>
+ </message>
+ <message>
+ <source>Perform copy and rotate</source>
+ <translation>Effectuer une copie et une rotation</translation>
+ </message>
+ </context>
+ <context>
+ <name>AngularCopy:axis_angular</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for the axis of rotation</source>
+ <translation>Sélectionnez une arête pour l'axe de rotation</translation>
+ </message>
+ </context>
+ <context>
+ <name>AngularCopy:axis_angular:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>AngularCopy:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>AngularCopy:nb_angular</name>
+ <message>
+ <source>Nb copies</source>
+ <translation>Nb copies</translation>
+ </message>
+ <message>
+ <source>Number of copies for the angular copy</source>
+ <translation>Nombre de copies pour la copie angulaire</translation>
+ </message>
+ </context>
+ <context>
+ <name>AngularCopy:step_angular</name>
+ <message>
+ <source>Angular step</source>
+ <translation>Pas angulaire</translation>
+ </message>
+ <message>
+ <source>Step for the angular direction</source>
+ <translation>Pas pour la direction angulaire</translation>
+ </message>
+ </context>
+
+ <!-- LinearCopy -->
+ <context>
+ <name>LinearCopy</name>
+ <message>
+ <source>Linear copy</source>
+ <translation>Copie linéaire</translation>
+ </message>
+ <message>
+ <source>Perform copy and translate</source>
+ <translation>Effectuer la copie et la translation</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:axis_first_dir</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for the first direction</source>
+ <translation>Sélectionnez une arête pour la première direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:axis_first_dir:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:axis_second_dir</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for the second direction</source>
+ <translation>Sélectionnez une arête pour la deuxième direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:nb_first_dir</name>
+ <message>
+ <source>Nb copies</source>
+ <translation>Nb copies</translation>
+ </message>
+ <message>
+ <source>Number of copies for the first direction</source>
+ <translation>Nombre de copies pour la première direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:nb_second_dir</name>
+ <message>
+ <source>Nb copies</source>
+ <translation>Nb copies</translation>
+ </message>
+ <message>
+ <source>Number of copies for the second direction</source>
+ <translation>Nombre de copies pour la deuxième direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:step_first_dir</name>
+ <message>
+ <source>Step</source>
+ <translation>Étape</translation>
+ </message>
+ <message>
+ <source>Step for the first direction</source>
+ <translation>Pas pour la première direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:step_second_dir</name>
+ <message>
+ <source>Step</source>
+ <translation>Étape</translation>
+ </message>
+ <message>
+ <source>Step for the second direction</source>
+ <translation>Pas pour la deuxième direction</translation>
+ </message>
+ </context>
+ <context>
+ <name>LinearCopy:use_second_dir</name>
+ <message>
+ <source>Second direction</source>
+ <translation>Deuxième direction</translation>
+ </message>
+ </context>
+
+ <!-- Measurement -->
+ <context>
+ <name>Measurement</name>
+ <message>
+ <source>Calculate properties of objects</source>
+ <translation>Calculer les propriétés des objets</translation>
+ </message>
+ <message>
+ <source>Measurement</source>
+ <translation>Mesure</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:MeasureKind</name>
+ <message>
+ <source>Angle between edges</source>
+ <translation>Angle entre les bords</translation>
+ </message>
+ <message>
+ <source>Angle by 3 points</source>
+ <translation>Angle de 3 points</translation>
+ </message>
+ <message>
+ <source>Distance between objects</source>
+ <translation>Distance entre objets</translation>
+ </message>
+ <message>
+ <source>Edge length</source>
+ <translation>Longueur de bord</translation>
+ </message>
+ <message>
+ <source>Radius of circular edge, cylindrical surface or sphere</source>
+ <translation>Rayon du bord circulaire, de la surface cylindrique ou de la sphère</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_from</name>
+ <message>
+ <source>First edge</source>
+ <translation>Premier bord</translation>
+ </message>
+ <message>
+ <source>Select an edge</source>
+ <translation>Sélectionnez une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_from:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_point_1</name>
+ <message>
+ <source>Select a point</source>
+ <translation>Sélectionnez un point</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_point_1:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_point_2</name>
+ <message>
+ <source>Angle apex</source>
+ <translation>Sommet de l’angle</translation>
+ </message>
+ <message>
+ <source>Select a point</source>
+ <translation>Sélectionnez un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_point_2:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_point_3</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ <message>
+ <source>Select a point</source>
+ <translation>Sélectionnez un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_point_3:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_to</name>
+ <message>
+ <source>Second edge</source>
+ <translation>Deuxième bord</translation>
+ </message>
+ <message>
+ <source>Select an edge</source>
+ <translation>Sélectionnez une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:angle_to:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:circular</name>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Select an edge or face</source>
+ <translation>Sélectionnez une arête ou une face</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:distance_from</name>
+ <message>
+ <source>From</source>
+ <translation>De</translation>
+ </message>
+ <message>
+ <source>Select a shape</source>
+ <translation>Sélectionnez une forme</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:distance_to</name>
+ <message>
+ <source>Select a shape</source>
+ <translation>Sélectionnez une forme</translation>
+ </message>
+ <message>
+ <source>To</source>
+ <translation>À</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:edge_for_length</name>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <source>Select an edge</source>
+ <translation>Sélectionnez une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>Measurement:edge_for_length:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+
+ <!-- Placement -->
+ <context>
+ <name>Placement</name>
+ <message>
+ <source>Place objects relatively to another one</source>
+ <translation>Placez les objets l'un par rapport à l'autre</translation>
+ </message>
+ <message>
+ <source>Placement</source>
+ <translation>Placement</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_centering</name>
+ <message>
+ <source>Center faces under placement</source>
+ <translation>Faces centrales en cours de placement</translation>
+ </message>
+ <message>
+ <source>Centering</source>
+ <translation>Centrage</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_end_shape</name>
+ <message>
+ <source>Select an end face, edge or vertex</source>
+ <translation>Sélectionnez une extrémité, une arête ou un sommet</translation>
+ </message>
+ <message>
+ <source>Select an object</source>
+ <translation>Sélectionnez un objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_end_shape:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Context is empty.</source>
+ <translation>Erreur : le contexte est vide.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_objects_list</name>
+ <message>
+ <source>Select objects</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ <message>
+ <source>Select objects to move</source>
+ <translation>Sélectionnez les objets à déplacer</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_reverse_direction</name>
+ <message>
+ <source>Reverse</source>
+ <translation>Sens inverse</translation>
+ </message>
+ <message>
+ <source>Reverse placement direction</source>
+ <translation>Sens de placement inverse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_start_shape</name>
+ <message>
+ <source>Select a start face, edge or vertex</source>
+ <translation>Sélectionnez une face de début, une arête ou un sommet</translation>
+ </message>
+ <message>
+ <source>Select an object</source>
+ <translation>Sélectionnez un objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>Placement:placement_start_shape:GeomValidators_BodyShapes</name>
+ <message>
+ <source>Error: Context is empty.</source>
+ <translation>Erreur : le contexte est vide.</translation>
+ </message>
+ </context>
+
+ <!-- Rotation -->
+ <context>
+ <name>Rotation</name>
+ <message>
+ <source>Perform rotation of objects around the axis to specified angle</source>
+ <translation>Effectuer une rotation des objets autour de l'axe avec l'angle spécifié</translation>
+ </message>
+ <message>
+ <source>Rotation</source>
+ <translation>Rotation</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:CreationMethod</name>
+ <message>
+ <source>By a center and two points</source>
+ <translation>Par un centre et deux points</translation>
+ </message>
+ <message>
+ <source>By an axis and an angle</source>
+ <translation>Par un axe et un angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:axis_object</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for axis</source>
+ <translation>Sélectionnez une arête pour l'axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:center_point</name>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ <message>
+ <source>Select a center point</source>
+ <translation>Sélectionnez un point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:center_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:end_point</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ <message>
+ <source>Select an end point</source>
+ <translation>Sélectionnez un point d'arrivée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:end_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select solid objects</source>
+ <translation>Sélectionner des objets solides</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:start_point</name>
+ <message>
+ <source>Select a starting point</source>
+ <translation>Sélectionnez un point de départ</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>Rotation:start_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+
+ <!-- Symmetry -->
+ <context>
+ <name>Symmetry</name>
+ <message>
+ <source>Perform symmetry with respect to a point, an axis or a plane</source>
+ <translation>Effectuer une symétrie par rapport à un point, un axe ou un plan</translation>
+ </message>
+ <message>
+ <source>Symmetry</source>
+ <translation>Symétrie</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:CreationMethod</name>
+ <message>
+ <source>Axis reflection</source>
+ <translation>Axe de réflexion</translation>
+ </message>
+ <message>
+ <source>Plane reflection</source>
+ <translation>Réflexion plane</translation>
+ </message>
+ <message>
+ <source>Point reflection</source>
+ <translation>Point de réflexion</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:axis_object</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an axis</source>
+ <translation>Sélectionnez un axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:axis_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:keep_original</name>
+ <message>
+ <source>Do not remove original shape</source>
+ <translation>Ne pas enlever la forme originale</translation>
+ </message>
+ <message>
+ <source>Keep original result</source>
+ <translation>Conserver le résultat original</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select solid objects</source>
+ <translation>Sélectionner des objets solides</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:plane_object</name>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ <message>
+ <source>Select a plane</source>
+ <translation>Sélectionnez un plan</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:point_object</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Select a point</source>
+ <translation>Sélectionnez un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Symmetry:point_object:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+
+ <!-- Translation -->
+ <context>
+ <name>Translation</name>
+ <message>
+ <source>Perform translation of objects along the axis to specified distance</source>
+ <translation>Effectuer la translation des objets le long de l'axe à la distance spécifiée</translation>
+ </message>
+ <message>
+ <source>Translation</source>
+ <translation>Translation</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:CreationMethod</name>
+ <message>
+ <source>By X, Y and Z dimensions</source>
+ <translation>Par dimensions X, Y et Z</translation>
+ </message>
+ <message>
+ <source>By an axis and a distance</source>
+ <translation>Par un axe et une distance</translation>
+ </message>
+ <message>
+ <source>By two points</source>
+ <translation>Par deux points</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:axis_object</name>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Select an edge for axis</source>
+ <translation>Sélectionnez une arête pour l'axe</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'axe de translation n'est pas sélectionné.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:distance</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:dx</name>
+ <message>
+ <source>DX</source>
+ <translation>DX</translation>
+ </message>
+ <message>
+ <source>Dimension in X</source>
+ <translation>Dimension en X</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:dy</name>
+ <message>
+ <source>DY</source>
+ <translation>DY</translation>
+ </message>
+ <message>
+ <source>Dimension in Y</source>
+ <translation>Dimension en Y</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:dz</name>
+ <message>
+ <source>DZ</source>
+ <translation>DZ</translation>
+ </message>
+ <message>
+ <source>Dimension in Z</source>
+ <translation>Dimension en Z</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:end_point</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ <message>
+ <source>Select the end point to define the axis</source>
+ <translation>Sélectionnez le point final pour définir l'axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:end_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:main_objects</name>
+ <message>
+ <source>Main objects</source>
+ <translation>Objets principaux</translation>
+ </message>
+ <message>
+ <source>Select solid objects</source>
+ <translation>Sélectionner des objets solides</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:start_point</name>
+ <message>
+ <source>Select the start point to define the axis</source>
+ <translation>Sélectionnez le point de départ pour définir l'axe</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>Translation:start_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+
+</TS>
model.testResultsVolumes(Fuse_1, [785.398163397447774514148477465])
Fuse_2 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1_3"), model.selection("SOLID", "Extrusion_1_1_1")], [model.selection("FACE", "Fuse_1_1_1")])
-assert(Fuse_2.feature().error() != "")
+model.testNbResults(Fuse_2, 1)
+model.testNbSubResults(Fuse_2, [2])
+model.testNbSubShapes(Fuse_2, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Fuse_2, GeomAPI_Shape.FACE, [19])
+model.testNbSubShapes(Fuse_2, GeomAPI_Shape.EDGE, [82])
+model.testNbSubShapes(Fuse_2, GeomAPI_Shape.VERTEX, [164])
+model.testResultsVolumes(Fuse_2, [25803.607097738855372881516814232])
model.end()
Part_1_doc.removeFeature(Fuse_1.feature())
Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Partition_1_1_1"), model.selection("SOLID", "Partition_1_1_2")])
-assert(Fuse_1.feature().error() != "")
+# after merging Union and Fuse features, fusing of solids in the same composolid should work (issue #3062)
+assert(Fuse_1.feature().error() == "")
Part_1_doc.removeFeature(Fuse_1.feature())
Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Partition_1_1_1")], [model.selection("SOLID", "Partition_1_1_2")])
-assert(Fuse_1.feature().error() != "")
+# after merging Union and Fuse features, fusing of solids in the same composolid should work (issue #3062)
+assert(Fuse_1.feature().error() == "")
Part_1_doc.removeFeature(Fuse_1.feature())
model.end()
from GeomAPI import GeomAPI_Shape
model.testNbResults(Fuse_1, 1)
-model.testNbSubResults(Fuse_1, [1])
+model.testNbSubResults(Fuse_1, [0])
model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [0])
model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [1])
model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [2])
Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Compound_1_1_1_1")], [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("FACE", "Compound_1_1_2")], True)
model.end()
-assert(Fuse_1.feature().error() != "")
+from GeomAPI import *
+
+model.testNbResults(Fuse_1, 1)
+model.testNbSubResults(Fuse_1, [2])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [2])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [16])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [78])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.VERTEX, [156])
+model.testResultsVolumes(Fuse_1, [1589.048622670478835])
model.testNbResults(Fuse_1, 1)
model.testNbSubResults(Fuse_1, [2])
-model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [6])
-model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [23])
-model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [70])
-model.testNbSubShapes(Fuse_1, GeomAPI_Shape.VERTEX, [140])
-model.testResultsVolumes(Fuse_1, [5016.039439659862])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [7])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [31])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [108])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.VERTEX, [216])
+model.testResultsVolumes(Fuse_1, [5516.039439659862])
assert(model.checkPythonDump())
Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Compound_1_1_1_1")], [model.selection("SOLID", "LinearCopy_2_1_1_1"), model.selection("FACE", "Compound_1_1_2")], True, keepSubResults = True)
model.end()
-assert(Fuse_1.feature().error() != "")
+from GeomAPI import *
+
+model.testNbResults(Fuse_1, 1)
+model.testNbSubResults(Fuse_1, [4])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.SOLID, [9])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.FACE, [44])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.EDGE, [160])
+model.testNbSubShapes(Fuse_1, GeomAPI_Shape.VERTEX, [320])
+model.testResultsVolumes(Fuse_1, [6516.03943965772123])
--- /dev/null
+# Copyright (C) 2018-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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+import math
+
+def checkMiddlePoint(shape, x, y, z, tolerance = 1.e-7):
+ assert(shape is not None)
+ middlePoint = shape.middlePoint()
+ assert(math.fabs(middlePoint.x() - x) < tolerance), "{} != {}".format(middlePoint.x(), x)
+ assert(math.fabs(middlePoint.y() - y) < tolerance), "{} != {}".format(middlePoint.y(), y)
+ assert(math.fabs(middlePoint.z() - z) < tolerance), "{} != {}".format(middlePoint.z(), z)
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Axis_1 = model.addAxis(Part_1_doc, 0, -10, 10)
+
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), [model.selection("SOLID", "Box_1_1")])
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Left"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(5, 10, 2)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchCircle_1.center())
+ExtrusionCut_1.setNestedSketch(Sketch_1)
+model.do()
+Shape = ExtrusionCut_1.results()[0].resultSubShapePair()[0].shape()
+checkMiddlePoint(Shape, 5.0, 5.0, 4.97049495)
+
+ExtrusionCut_1.setDirection(model.selection("EDGE", "Axis_1"))
+model.do()
+Shape = ExtrusionCut_1.results()[0].resultSubShapePair()[0].shape()
+checkMiddlePoint(Shape, 4.99796028, 5.00196717, 4.97487226)
+
+ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], [model.selection("SOLID", "ExtrusionCut_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Front"))
+SketchCircle_2 = Sketch_2.addCircle(2, 7, 1.5)
+ExtrusionCut_2.setNestedSketch(Sketch_2)
+model.do()
+
+ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [], [model.selection("SOLID", "ExtrusionCut_2_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_2_1/Modified_Face&Box_1_1/Front"))
+SketchCircle_3 = Sketch_3.addCircle(7, 2, 1.5)
+ExtrusionCut_3.setNestedSketch(Sketch_3)
+model.do()
+Shape = ExtrusionCut_3.results()[0].resultSubShapePair()[0].shape()
+checkMiddlePoint(Shape, 4.99787246, 4.92218515, 4.91081244)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2018-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
+#
+
+from salome.shaper import model
+from GeomAPI import *
+
+import math
+
+def checkMiddlePoint(shape, x, y, z, tolerance = 1.e-7):
+ assert(shape is not None)
+ middlePoint = shape.middlePoint()
+ assert(math.fabs(middlePoint.x() - x) < tolerance), "{} != {}".format(middlePoint.x(), x)
+ assert(math.fabs(middlePoint.y() - y) < tolerance), "{} != {}".format(middlePoint.y(), y)
+ assert(math.fabs(middlePoint.z() - z) < tolerance), "{} != {}".format(middlePoint.z(), z)
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_2 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_3 = model.addBox(Part_1_doc, 20, 20, 20)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_2_1")], 20, 10, 0)
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_3_1")], 40, 20, 0)
+Edge_1 = model.addEdge(Part_1_doc, model.selection("VERTEX", "[Box_1_1/Back][Box_1_1/Left][Box_1_1/Bottom]"), model.selection("VERTEX", "[Translation_2_1/MF:Translated&Box_3_1/Front][Translation_2_1/MF:Translated&Box_3_1/Right][Translation_2_1/MF:Translated&Box_3_1/Top]"))
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Back"))
+SketchCircle_1 = Sketch_1.addCircle(2.134236344973221, -2.430731739079631, 1.564909384334321)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")])
+ExtrusionFuse_1_objects_2 = [model.selection("SOLID", "Box_1_1"), model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Translation_2_1")]
+ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [model.selection("FACE", "Face_1_1")], model.selection("EDGE", "Edge_1_1"), ExtrusionFuse_1_objects_2)
+
+model.do()
+Shape = ExtrusionFuse_1.results()[0].resultSubShapePair()[0].shape()
+checkMiddlePoint(Shape, 37.46245068, 23.05267081, 8.52187757)
+
+model.end()
+
+assert(model.checkPythonDump())
SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_1.result())
SketchConstraintEqual_4 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_1.result())
SketchConstraintEqual_5 = Sketch_1.setEqual(SketchLine_6.result(), SketchLine_1.result())
-SketchConstraintAngle_1 = Sketch_1.setAngleBackward(SketchLine_1.result(), SketchLine_2.result(), 120)
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_1.result(), SketchLine_2.result(), 120)
SketchConstraintAngle_2 = Sketch_1.setAngle(SketchLine_3.result(), SketchLine_2.result(), 120)
-SketchConstraintAngle_3 = Sketch_1.setAngleBackward(SketchLine_3.result(), SketchLine_4.result(), 120)
+SketchConstraintAngle_3 = Sketch_1.setAngle(SketchLine_3.result(), SketchLine_4.result(), 120)
SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_2.result())
SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_5.result(), 60)
SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
aBaseObject.setValue(aPipeFeature)
aRecoveredObjects = aRecover.reflist("recovered")
aRecoveredObjects.append(aFaceResult1)
+aRecoveredObjects.append(aWireResult)
aSession.finishOperation()
# Create pipe with bi-normal
aSession.startOperation()
aPipeFeature = aPart.addFeature("Pipe")
aBaseObjectsList = aPipeFeature.selectionList("base_objects")
-aBaseObjectsList.append(aRecover.firstResult(), None)
+aBaseObjectsList.append(aRecover.lastResult(), None)
aPathObjectSelection = aPipeFeature.selection("path_object")
-aPathObjectSelection.setValue(aWireResult, None)
+aPathObjectSelection.setValue(aRecover.firstResult(), None)
aPipeFeature.string("creation_method").setValue("binormal")
aBinormalObjectSelection = aPipeFeature.selection("binormal")
aShapeExplorer = GeomAPI_ShapeExplorer(aSketchShape, GeomAPI_Shape.EDGE)
aBaseObject.setValue(aPipeFeature)
aRecoveredObjects = aRecover2.reflist("recovered")
aRecoveredObjects.append(aRecover.firstResult())
+aRecoveredObjects.append(aRecover.lastResult())
aSession.finishOperation()
# Create pipe with locations
aBaseObjectsList.append(aRecover2.firstResult(), None)
aBaseObjectsList.append(aFaceResult2, None)
aPathObjectSelection = aPipeFeature.selection("path_object")
-aPathObjectSelection.setValue(aWireResult, None)
+aPathObjectSelection.setValue(aRecover2.lastResult(), None)
aPipeFeature.string("creation_method").setValue("locations")
aSession.finishOperation()
--- /dev/null
+# Copyright (C) 2018-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
+#
+
+from salome.shaper import model
+
+import math
+
+def checkMiddlePoint(shape, x, y, z, tolerance = 1.e-7):
+ assert(shape is not None)
+ middlePoint = shape.middlePoint()
+ assert(math.fabs(middlePoint.x() - x) < tolerance), "{} != {}".format(middlePoint.x(), x)
+ assert(math.fabs(middlePoint.y() - y) < tolerance), "{} != {}".format(middlePoint.y(), y)
+ assert(math.fabs(middlePoint.z() - z) < tolerance), "{} != {}".format(middlePoint.z(), z)
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 2, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], 5, 5, 0)
+
+RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")])
+
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]__cc"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]"), False)
+SketchCircle_1 = SketchProjection_2.createdFeature()
+SketchCircle_2 = Sketch_1.addCircle(5, 5, 2)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_2.center())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+
+RevolutionCut_1.setNestedSketch(Sketch_1)
+
+model.do()
+
+Shape = RevolutionCut_1.results()[0].resultSubShapePair()[0].shape()
+checkMiddlePoint(Shape, 5.13562827, 5.0, 5.13562827)
+
+model.end()
+
+assert(model.checkPythonDump())
--- /dev/null
+# Copyright (C) 2018-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
+#
+
+from salome.shaper import model
+
+import math
+
+def checkMiddlePoint(shape, x, y, z, tolerance = 1.e-7):
+ assert(shape is not None)
+ middlePoint = shape.middlePoint()
+ assert(math.fabs(middlePoint.x() - x) < tolerance), "{} != {}".format(middlePoint.x(), x)
+ assert(math.fabs(middlePoint.y() - y) < tolerance), "{} != {}".format(middlePoint.y(), y)
+ assert(math.fabs(middlePoint.z() - z) < tolerance), "{} != {}".format(middlePoint.z(), z)
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Cylinder_1 = model.addCylinder(Part_1_doc, model.selection("VERTEX", "PartSet/Origin"), model.selection("EDGE", "PartSet/OZ"), 2, 10)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Cylinder_1_1")], 5, 5, 0)
+
+RevolutionFuse_1 = model.addRevolutionFuse(Part_1_doc, [], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")])
+
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Translation_1_1/MF:Translated&Cylinder_1_1/Face_2"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]__cc"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "[Translation_1_1/MF:Translated&Cylinder_1_1/Face_1][Translation_1_1/MF:Translated&Cylinder_1_1/Face_2]"), False)
+SketchCircle_1 = SketchProjection_2.createdFeature()
+SketchCircle_2 = Sketch_1.addCircle(5, 5, 2)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_2.center())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchCircle_1.results()[1], SketchCircle_2.results()[1])
+
+RevolutionFuse_1.setNestedSketch(Sketch_1)
+
+model.do()
+
+Shape = RevolutionFuse_1.results()[0].resultSubShapePair()[0].shape()
+checkMiddlePoint(Shape, 7.01705635, 5.0, 7.01705635)
+
+model.end()
+
+assert(model.checkPythonDump())
# Make union on extrusion
#=========================================================================
aSession.startOperation()
-aUnionFeature = aPart.addFeature("Union")
-aUnionFeature.selectionList("base_objects").append(anExtrusionResult.subResult(0), None);
-aUnionFeature.selectionList("base_objects").append(anExtrusionResult.subResult(1), None);
-aUnionFeature.selectionList("base_objects").append(anExtrusionResult.subResult(2), None);
+aUnionFeature = aPart.addFeature("Fuse")
+aUnionFeature.string("creation_method").setValue("simple")
+aUnionFeature.selectionList("main_objects").append(anExtrusionResult.subResult(0), None);
+aUnionFeature.selectionList("main_objects").append(anExtrusionResult.subResult(1), None);
+aUnionFeature.selectionList("main_objects").append(anExtrusionResult.subResult(2), None);
+aUnionFeature.boolean("remove_intersection_edges").setValue(False)
aSession.finishOperation()
assert (len(aUnionFeature.results()) > 0)
anUnionResult = modelAPI_ResultBody(aUnionFeature.firstResult())
Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_1/SketchArc_1_2")])
Revolution_1 = model.addRevolution(Part_1_doc, [model.selection("EDGE", "Edge_1_1")], model.selection("EDGE", "PartSet/OY"), 200, 0)
Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "PartSet/XOZ"), model.selection("FACE", "Revolution_1_1")])
-Union_1 = model.addUnion(Part_1_doc, [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_2")])
+Union_1 = model.addFuse(Part_1_doc, [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_2")], True)
model.do()
model.checkResult(Union_1,model,1,[0],[0],[1],[4],[8])
Partition_1_objects = [model.selection("FACE", "PartSet/YOZ"), model.selection("FACE", "PartSet/XOZ"), model.selection("FACE", "PartSet/XOY"), model.selection("FACE", "Revolution_1_1")]
Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
Union_1_objects = [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_2"), model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4")]
-Union_1 = model.addUnion(Part_1_doc, Union_1_objects)
+Union_1 = model.addFuse(Part_1_doc, Union_1_objects, True)
model.testHaveNamingSubshapes(Union_1,model,Part_1_doc)
model.do()
model.end()
Partition_1_objects = [model.selection("FACE", "Face_2_1"), model.selection("FACE", "Face_1_1"), model.selection("FACE", "PartSet/YOZ")]
Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
Union_1_objects = [model.selection("FACE", "Partition_1_1_1"), model.selection("FACE", "Partition_1_1_3"), model.selection("FACE", "Partition_1_1_4")]
-Union_1 = model.addUnion(Part_1_doc, Union_1_objects)
+Union_1 = model.addFuse(Part_1_doc, Union_1_objects, True, keepSubResults = True)
model.do()
model.checkResult(Union_1,model,1,[2],[0],[2],[13],[26])
-#model.testHaveNamingSubshapes(Union_1,model,Part_1_doc)
+model.testHaveNamingSubshapes(Union_1,model,Part_1_doc)
model.end()
Plane_5 = model.addPlane(Part_1_doc, model.selection("FACE", "Box_1_1/Front"), 5, True)
Partition_1_objects = [model.selection("FACE", "Plane_1"), model.selection("FACE", "Plane_2"), model.selection("SOLID", "Box_1_1")]
Partition_1 = model.addPartition(Part_1_doc, Partition_1_objects)
-Union_1 = model.addUnion(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3"), model.selection("SOLID", "Partition_1_1_1")])
-Union_2 = model.addUnion(Part_1_doc, [model.selection("SOLID", "Union_1_1_2"), model.selection("SOLID", "Union_1_1_1")])
+Union_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Partition_1_1_3"), model.selection("SOLID", "Partition_1_1_1")], False, keepSubResults = True)
+Union_2 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Fuse_1_1_2"), model.selection("SOLID", "Fuse_1_1_1")], False, keepSubResults = True)
model.do()
model.end()
--- /dev/null
+
+ .. _tui_create_extrusion_cut_through_all:
+
+Create Extrusion Cut through all objects
+========================================
+
+.. literalinclude:: examples/extrusion_cut_through_all.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/extrusion_cut_through_all.py>`
+
--- /dev/null
+
+ .. _tui_create_extrusion_fuse_through_all:
+
+Create Extrusion Fuse through all objects
+========================================
+
+.. literalinclude:: examples/extrusion_fuse_through_all.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/extrusion_fuse_through_all.py>`
+
--- /dev/null
+
+ .. _tui_create_revolution_cut_through_all:
+
+Create Revolution Cut by 360 degrees
+====================================
+
+.. literalinclude:: examples/revolution_cut_through_all.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/revolution_cut_through_all.py>`
+
--- /dev/null
+
+ .. _tui_create_revolution_fuse_through_all:
+
+Create Revolution Fuse by 360 degrees
+=====================================
+
+.. literalinclude:: examples/revolution_fuse_through_all.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/revolution_fuse_through_all.py>`
+
--- /dev/null
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc,
+ [],
+ model.selection(),
+ [model.selection("SOLID", "Box_1_1")])
+Sketch_1 = model.addSketch(Part_1_doc,
+ model.selection("FACE", "Box_1_1/Top"))
+SketchCircle_1 = Sketch_1.addCircle(5, 0, 2)
+ExtrusionCut_1.setNestedSketch(Sketch_1)
+model.do()
+model.end()
--- /dev/null
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+# Objects to be cut
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_2 = model.addBox(Part_1_doc, 10, 10, 10)
+Box_3 = model.addBox(Part_1_doc, 20, 20, 20)
+Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_2_1")], 20, 10, 0)
+Translation_2 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_3_1")], 40, 20, 0)
+ExtrusionFuse_1_objects_2 = [model.selection("SOLID", "Box_1_1"),
+ model.selection("SOLID", "Translation_1_1"),
+ model.selection("SOLID", "Translation_2_1")]
+
+# Extrusion direction
+Point_1 = model.addPoint(Part_1_doc, 0, 0, 0)
+Point_2 = model.addPoint(Part_1_doc, 60, 40, 20)
+Edge_1 = model.addEdge(Part_1_doc, model.selection("VERTEX", "Point_1"), model.selection("VERTEX", "Point_2"))
+
+# Base object for extrusion
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Back"))
+SketchCircle_1 = Sketch_1.addCircle(2.13, -2.43, 1.6)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")])
+
+# Extrusion fuse through all
+ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc,
+ [model.selection("FACE", "Face_1_1")],
+ model.selection("EDGE", "Edge_1_1"),
+ ExtrusionFuse_1_objects_2)
+
+model.do()
+model.end()
--- /dev/null
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top"))
+SketchCircle_1 = Sketch_1.addCircle(5, 5, 2.5)
+model.do()
+RevolutionCut_1 = model.addRevolutionCut(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")])
+model.do()
+model.end()
--- /dev/null
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top"))
+SketchCircle_1 = Sketch_1.addCircle(5, 5, 2.5)
+model.do()
+RevolutionFuse_1 = model.addRevolutionFuse(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection("EDGE", "[Box_1_1/Front][Box_1_1/Top]"), [model.selection("SOLID", "Box_1_1")])
+model.do()
+model.end()
.. centered::
Start sketch
-There are two variants of the property panel for Extrusion Cut depending on the chosen option:
+There are three variants of the property panel for Extrusion Cut depending on the chosen option:
.. image:: images/extrusion_by_sizes.png
:align: left
:align: left
**By Bounding Planes** extrudes objects by specifying bounding planes and offsets.
+.. image:: images/extrusion_through_all.png
+ :align: left
+**Through All** extrudes base objects through all objects to be cut.
+
By sizes
--------
- **Axis** - if selected, it will be the direction of extrusion, otherwise objects normals will be used.
- **To size** - size for extrusion in the direction.
- **From size** - size for extrusion in the opposite direction.
-- **Cut from** - contains a list of objects which will be cut from the result of extrusion.
+- **Cut from** - contains a list of objects to be cut by the result of extrusion.
**TUI Commands**:
- **To offset** - offset for extrusion or for a bounding plane, if selected.
- **From plane** - a planar face can be selected to bound extrusion from the other side.
- **From offset** - offset for extrusion or for a bounding plane, if selected.
-- **Cut from** - contains a list of objects which will be cut from the result of extrusion.
+- **Cut from** - contains a list of objects which will be cut by the result of extrusion.
**TUI Commands**:
**Created Extrusion Cut**
**See Also** a sample TUI Script of :ref:`tui_create_extrusion_cut_by_bounding_planes` operation.
+
+Through all
+-----------
+
+.. image:: images/ExtrusionCut3.png
+ :align: center
+
+.. centered::
+ Extrusion Cut: definition through all objects
+
+- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be extruded.
+- **Axis** - if selected, it will be the direction of extrusion, otherwise objects normals will be used.
+- **Cut from** - contains a list of objects to be cut by the result of extrusion.
+
+**TUI Commands**:
+
+.. py:function:: model.addExtrusionCut(part, objectsToExtrude, objectsToCut)
+
+ :param part: The current part object.
+ :param list: A list of objects for extrusion.
+ :param list: A list of objects to cut from.
+ :return: Created object.
+
+.. py:function:: model.addExtrusionCut(part, objects, direction, objectsToCut)
+
+ :param part: The current part object.
+ :param list: A list of objects for extrusion.
+ :param object: A direction of extrusion
+ :param list: A list of objects to cut from.
+ :return: Created object.
+
+Result
+""""""
+
+The Result of the operation will be an extruded shape:
+
+.. image:: images/extrusion_cut_through_all_result.png
+ :align: center
+
+.. centered::
+ **Created Extrusion Cut**
+
+**See Also** a sample TUI Script of :ref:`tui_create_extrusion_cut_through_all` operation.
.. centered::
Start sketch
-There are two variants of the property panel for Extrusion Fuse depending on the chosen option:
+There are three variants of the property panel for Extrusion Fuse depending on the chosen option:
.. image:: images/extrusion_by_sizes.png
:align: left
:align: left
**By Bounding Planes** extrudes objects by specifying bounding planes and offsets.
+.. image:: images/extrusion_through_all.png
+ :align: left
+**Through All** extrudes base objects to pass through all objects fuse with.
+
By sizes
--------
**Extrusion Fuse created**
**See Also** a sample TUI Script of :ref:`tui_create_extrusion_fuse_by_bounding_planes` operation.
+
+Through all
+-----------
+
+.. image:: images/ExtrusionFuse3.png
+ :align: center
+
+.. centered::
+ Extrusion Fuse: definition through all objects
+
+- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be extruded.
+- **Axis** - if selected, it will be the direction of extrusion, otherwise objects normals will be used.
+- **Fuse with** - contains a list of objects which will be fused with the result of extrusion.
+
+**TUI Commands**:
+
+.. py:function:: model.addExtrusionFuse(part, objectsToExtrude, objectsToFuse)
+
+ :param part: The current part object.
+ :param list: A list of objects for extrusion.
+ :param list: A list of objects to fuse with.
+ :return: Created object.
+
+.. py:function:: model.addExtrusionFuse(part, objectsToExtrude, direction, objectsToFuse)
+
+ :param part: The current part object.
+ :param list: A list of objects for extrusion.
+ :param object: A direction of extrusion
+ :param list: A list of objects to fuse with.
+ :return: Created object.
+
+Result
+""""""
+
+The Result of the operation will be an extruded shape:
+
+.. image:: images/extrusion_fuse_through_all_result.png
+ :align: center
+
+.. centered::
+ **Extrusion Fuse created**
+
+**See Also** a sample TUI Script of :ref:`tui_create_extrusion_fuse_through_all` operation.
.. centered::
Start sketch
-There are two variants of the property panel for Revolution Cut depending on the chosen option:
+There are three variants of the property panel for Revolution Cut depending on the chosen option:
.. image:: images/revolution_by_angles.png
:align: left
:align: left
**By Bounding Planes** revolves objects by specifying bounding planes and angles.
+.. image:: images/revolution_through_all.png
+ :align: left
+**Through All** revolves objects by 360 degrees.
+
By angles
--------
.. centered::
**Revolution Cut created**
-**See Also** a sample TUI Script of :ref:`tui_create_revolution_cut_by_bounding_planes` operation.
\ No newline at end of file
+**See Also** a sample TUI Script of :ref:`tui_create_revolution_cut_by_bounding_planes` operation.
+
+Through all
+--------
+
+.. image:: images/RevolutionCut3.png
+ :align: center
+
+.. centered::
+ Revolution Cut: revolving through all the space
+
+- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be revolved.
+- **Axis** - axis of revolution.
+- **Cut from** - contains a list of objects which will but cut with the result of revolution.
+
+**TUI Commands**:
+
+.. py:function:: model.addRevolutionCut(part, objectsToRevolve, axis, objectToCut)
+
+ :param part: The current part object.
+ :param list: A list of objects for revolution.
+ :param object: An axis.
+ :param list: A list of objects to cut from.
+ :return: Created object.
+
+Result
+""""""
+
+The Result of the operation will be a revolved shape:
+
+.. image:: images/revolution_cut_through_all_result.png
+ :align: center
+
+.. centered::
+ **Revolution Cut created**
+
+**See Also** a sample TUI Script of :ref:`tui_create_revolution_cut_through_all` operation.
.. centered::
Start sketch
-There are two variants of the property panel for Revolution Fuse depending on the chosen option:
+There are three variants of the property panel for Revolution Fuse depending on the chosen option:
.. image:: images/revolution_by_angles.png
:align: left
:align: left
**By Bounding Planes** revolves objects by specifying bounding planes and angles.
+.. image:: images/revolution_through_all.png
+ :align: left
+**Through All** revolves objects by 360 degrees.
+
By angles
--------
.. centered::
**Revolution Fuse created**
-**See Also** a sample TUI Script of :ref:`tui_create_revolution_fuse_by_bounding_planes` operation.
\ No newline at end of file
+**See Also** a sample TUI Script of :ref:`tui_create_revolution_fuse_by_bounding_planes` operation.
+
+Through All
+-----------
+
+.. image:: images/RevolutionFuse3.png
+ :align: center
+
+.. centered::
+ Revolution Fuse: definition by bounding planes
+
+- **Base objects** - contains a list of objects selected in the Object Browser or in the Viewer, which will be revolved.
+- **Axis** - axis of revolution.
+- **Fuse with** - contains a list of objects which will be fused with the result of revolution.
+
+**TUI Command**:
+
+.. py:function:: model.addRevolutionFuse(part, objectsToRevolve, axis, objectToFuse)
+
+ :param part: The current part object.
+ :param list: A list of objects for revolution.
+ :param object: An axis.
+ :param list: A list of objects to fuse with.
+ :return: Created object.
+
+Result
+""""""
+
+The Result of the operation will be a revolved shape:
+
+.. image:: images/revolution_fuse_through_all_result.png
+ :align: center
+
+.. centered::
+ **Revolution Fuse created**
+
+**See Also** a sample TUI Script of :ref:`tui_create_revolution_fuse_through_all` operation.
</doublevalue>
</groupbox>
</box>
+ <box id="ThroughAll" title="Through all" icon="icons/Features/extrusion_throughall_32x32.png">
+ </box>
</toolbox>
</groupbox>
<multi_selector id="main_objects"
</doublevalue>
</groupbox>
</box>
+ <box id="ThroughAll" title="Through all" icon="icons/Features/extrusion_throughall_32x32.png">
+ </box>
</toolbox>
</groupbox>
<multi_selector id="main_objects"
<shape_selector id="path_object"
label="Path object:"
tooltip="Select an edge or wire for path"
- shape_types="edge wire">
+ shape_types="edge wire"
+ concealment="true">
<validator id="FeaturesPlugin_ValidatorPipePath"/>
</shape_selector>
<toolbox id="creation_method">
<shape_selector id="binormal"
label="Bi-Normal:"
tooltip="Select an edge for Bi-Normal"
- shape_types="edge">
+ shape_types="edge"
+ concealment="true">
<validator id="GeomValidators_ShapeType" parameters="line"/>
</shape_selector>
</box>
<multi_selector id="locations_objects"
label="Locations:"
tooltip="Select one or more vertices to specify the locations"
- shape_types="vertex">
+ shape_types="vertex"
+ concealment="true">
<validator id="FeaturesPlugin_ValidatorPipeLocations"/>
</multi_selector>
</box>
</group>
<group id="Measurement">
<feature id="Measurement" title="Measurement" tooltip="Calculate properties of objects"
- icon="icons/Features/measurement.png" helpfile="measurementFeature.html">
+ icon="icons/Features/measurement.png" helpfile="measurementFeature.html" abort_confirmation="false">
<source path="measurement_widget.xml"/>
</feature>
</group>
</doublevalue>
</groupbox>
</box>
+ <box id="ThroughAll" title="Through all" icon="icons/Features/revol_throughall_32x32.png">
+ </box>
</toolbox>
</groupbox>
<multi_selector id="main_objects"
</doublevalue>
</groupbox>
</box>
+ <box id="ThroughAll" title="Through all" icon="icons/Features/revol_throughall_32x32.png">
+ </box>
</toolbox>
</groupbox>
<multi_selector id="main_objects"
ThreePoints2d* anAngle = MY_ANGLE;
gp_Dir2d aDir1(anAngle->myFirst.XY() - anAngle->myCenter.XY());
gp_Dir2d aDir2(anAngle->mySecond.XY() - anAngle->myCenter.XY());
- double aRes = aDir1.Angle(aDir2);
- if (aRes < 0.0) aRes += 2 * PI;
- return aRes;
+ return aDir1.Angle(aDir2);
}
bool GeomAPI_Angle2d::isReversed(int theIndex)
#include<GeomAPI_Lin.h>
#include<GeomAPI_Ax2.h>
#include<GeomAPI_Ellipse.h>
+#include<GeomAPI_Vertex.h>
#include <BRepAdaptor_Curve.hxx>
}
}
+void GeomAPI_Edge::vertices(std::shared_ptr<GeomAPI_Vertex>& theStartVertex,
+ std::shared_ptr<GeomAPI_Vertex>& theEndVertex) const
+{
+ const TopoDS_Edge& anEdge = impl<TopoDS_Edge>();
+ TopoDS_Vertex aStart, aEnd;
+ TopExp::Vertices(anEdge, aStart, aEnd);
+ theStartVertex.reset(new GeomAPI_Vertex);
+ theStartVertex->setImpl(new TopoDS_Vertex(aStart));
+ theEndVertex.reset(new GeomAPI_Vertex);
+ theEndVertex->setImpl(new TopoDS_Vertex(aEnd));
+}
+
static Handle(Geom_Curve) baseCurve(const TopoDS_Edge& theEdge)
{
double aFirst, aLast;
class GeomAPI_Circ;
class GeomAPI_Lin;
class GeomAPI_Ellipse;
+class GeomAPI_Vertex;
/**\class GeomAPI_Edge
* \ingroup DataModel
GEOMAPI_EXPORT
GeomAPI_Edge(const std::shared_ptr<GeomAPI_Shape>& theShape);
+ /// Return vertices of the edge;
+ GEOMAPI_EXPORT
+ void vertices(std::shared_ptr<GeomAPI_Vertex>& theStartVertex,
+ std::shared_ptr<GeomAPI_Vertex>& theEndVertex) const;
+
/// Returns \c true if edges have same underlying curve
GEOMAPI_EXPORT
virtual bool isSameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape) const;
return aPoint1.IsEqual(aPoint2, Precision::Confusion()) == Standard_True;
}
+
+
+
+bool GeomAPI_Vertex::GeometricComparator::operator()(const GeomVertexPtr& theVertex1,
+ const GeomVertexPtr& theVertex2) const
+{
+ const TopoDS_Vertex& aVertex1 = theVertex1->impl<TopoDS_Vertex>();
+ const TopoDS_Vertex& aVertex2 = theVertex2->impl<TopoDS_Vertex>();
+
+ gp_Pnt aPnt1 = BRep_Tool::Pnt(aVertex1);
+ gp_Pnt aPnt2 = BRep_Tool::Pnt(aVertex2);
+
+ bool isLess = aPnt1.X() + myTolerance < aPnt2.X();
+ if (!isLess && aPnt1.X() <= aPnt2.X() + myTolerance) {
+ isLess = aPnt1.Y() + myTolerance < aPnt2.Y();
+ if (!isLess && aPnt1.Y() <= aPnt2.Y() + myTolerance)
+ isLess = aPnt1.Z() + myTolerance < aPnt2.Z();
+ }
+ return isLess;
+}
/// Returns true if the current edge is geometrically equal to the given edge.
GEOMAPI_EXPORT
virtual bool isEqual(const std::shared_ptr<GeomAPI_Shape> theVert) const;
+
+public:
+ /// \brief Compare vertices geometrically
+ class GeometricComparator
+ {
+ public:
+ GEOMAPI_EXPORT
+ GeometricComparator(const double theTolerance = 1.e-7) : myTolerance(theTolerance)
+ {}
+
+ /// Return \c true if the first vertex is less than the second
+ GEOMAPI_EXPORT
+ bool operator ()(const std::shared_ptr<GeomAPI_Vertex>& theVertex1,
+ const std::shared_ptr<GeomAPI_Vertex>& theVertex2) const;
+ private:
+ double myTolerance;
+ };
+
};
//! Pointer on the object
GeomAlgoAPI_Prism.h
GeomAlgoAPI_Revolution.h
GeomAlgoAPI_Boolean.h
+ GeomAlgoAPI_ThroughAll.h
GeomAlgoAPI_Rotation.h
GeomAlgoAPI_Translation.h
GeomAlgoAPI_MakeShape.h
GeomAlgoAPI_Offset.h
GeomAlgoAPI_SolidClassifier.h
GeomAlgoAPI_MapShapesAndAncestors.h
+ GeomAlgoAPI_Projection.h
GeomAlgoAPI_Chamfer.h
)
GeomAlgoAPI_Prism.cpp
GeomAlgoAPI_Revolution.cpp
GeomAlgoAPI_Boolean.cpp
+ GeomAlgoAPI_ThroughAll.cpp
GeomAlgoAPI_Rotation.cpp
GeomAlgoAPI_Translation.cpp
GeomAlgoAPI_MakeShape.cpp
/// Redefinition of the generic method for the Fuse problem: OCCT 30481
GEOMALGOAPI_EXPORT virtual void modified(const GeomShapePtr theOldShape,
- ListOfShape& theNewShapes);
+ ListOfShape& theNewShapes);
private:
/// Builds resulting shape.
#include <GeomAPI_Wire.h>
#include <Bnd_Box.hxx>
+
+#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
-#include <BRepAdaptor_Curve.hxx>
#include <BRepAlgo.hxx>
#include <BRepAlgo_FaceRestrictor.hxx>
+#include <BRepAdaptor_Curve.hxx>
#include <BRepBndLib.hxx>
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepCheck_Analyzer.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepExtrema_ExtCF.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <BRepClass_FaceClassifier.hxx>
+#include <BRepLib_CheckCurveOnSurface.hxx>
+
+#include <BOPAlgo_Builder.hxx>
+
#include <Geom2d_Curve.hxx>
#include <Geom2d_Curve.hxx>
-#include <BRepLib_CheckCurveOnSurface.hxx>
-#include <BRep_Tool.hxx>
-#include <Geom_CylindricalSurface.hxx>
+
+#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ShapeIterator.h>
+
#include <GeomLib_IsPlanarSurface.hxx>
#include <GeomLib_Tool.hxx>
#include <GeomAPI_IntCS.hxx>
+
#include <gp_Pln.hxx>
#include <GProp_GProps.hxx>
+
#include <IntAna_IntConicQuad.hxx>
#include <IntAna_Quadric.hxx>
-#include <NCollection_Vector.hxx>
+
#include <ShapeAnalysis.hxx>
#include <ShapeAnalysis_Surface.hxx>
-#include <TopoDS_Builder.hxx>
+
+#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Vertex.hxx>
-#include <TopoDS.hxx>
+#include <TopoDS_Builder.hxx>
+
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
-#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
-#include <BOPAlgo_Builder.hxx>
-#include <BRepBuilderAPI_MakeVertex.hxx>
-#include <TopoDS_Edge.hxx>
+#include <NCollection_Vector.hxx>
//==================================================================================================
static GProp_GProps props(const TopoDS_Shape& theShape)
return aFixedWire;
}
+//==================================================================================================
std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_ShapeTools::wireToEdge(
const std::shared_ptr<GeomAPI_Wire>& theWire)
{
return anEdge;
}
+//==================================================================================================
ListOfShape GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(const GeomShapePtr& theShape)
{
ListOfShape aSubShapes;
}
return aSubShapes;
-}
\ No newline at end of file
+}
+
+//==================================================================================================
+static void getMinMaxPointsOnLine(const std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+ const gp_Dir theDir,
+ double& theMin, double& theMax)
+{
+ theMin = RealLast();
+ theMax = RealFirst();
+ // Project bounding points on theDir
+ for (std::list<std::shared_ptr<GeomAPI_Pnt> >::const_iterator
+ aPointsIt = thePoints.begin(); aPointsIt != thePoints.end(); aPointsIt++) {
+ const gp_Pnt& aPnt = (*aPointsIt)->impl<gp_Pnt>();
+ gp_Dir aPntDir (aPnt.XYZ());
+ Standard_Real proj = (theDir*aPntDir) * aPnt.XYZ().Modulus();
+ if (proj < theMin) theMin = proj;
+ if (proj > theMax) theMax = proj;
+ }
+}
+
+//==================================================================================================
+void GeomAlgoAPI_ShapeTools::computeThroughAll(const ListOfShape& theObjects,
+ const ListOfShape& theBaseShapes,
+ const std::shared_ptr<GeomAPI_Dir> theDir,
+ double& theToSize, double& theFromSize)
+{
+ // Bounding box of objects
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aBndObjs =
+ GeomAlgoAPI_ShapeTools::getBoundingBox(theObjects);
+ if (aBndObjs.size() != 8) {
+ return;
+ }
+
+ // Prism direction
+ if (theDir.get()) {
+ // One direction for all prisms
+ gp_Dir aDir = theDir->impl<gp_Dir>();
+
+ // Bounding box of the base
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aBndBases =
+ GeomAlgoAPI_ShapeTools::getBoundingBox(theBaseShapes);
+ if (aBndBases.size() != 8) {
+ return;
+ }
+
+ // Objects bounds
+ Standard_Real lowBnd, upperBnd;
+ getMinMaxPointsOnLine(aBndObjs, aDir, lowBnd, upperBnd);
+
+ // Base bounds
+ Standard_Real lowBase, upperBase;
+ getMinMaxPointsOnLine(aBndBases, aDir, lowBase, upperBase);
+
+ // ----------.-----.---------.--------------.-----------> theDir
+ // lowBnd lowBase upperBase upperBnd
+
+ theToSize = upperBnd - lowBase;
+ theFromSize = upperBase - lowBnd;
+ } else {
+ // Direction is a normal to each base shape (different normals to bases)
+ // So we calculate own sizes for each base shape
+ theToSize = 0.0;
+ theFromSize = 0.0;
+
+ for (ListOfShape::const_iterator anIt = theBaseShapes.begin();
+ anIt != theBaseShapes.end(); ++anIt) {
+ const GeomShapePtr& aBaseShape_i = (*anIt);
+ ListOfShape aBaseShapes_i;
+ aBaseShapes_i.push_back(aBaseShape_i);
+
+ // Bounding box of the base
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aBndBases =
+ GeomAlgoAPI_ShapeTools::getBoundingBox(aBaseShapes_i);
+ if (aBndBases.size() != 8) {
+ return;
+ }
+
+ // Direction (normal to aBaseShapes_i)
+ // Code like in GeomAlgoAPI_Prism
+ gp_Dir aDir;
+ const TopoDS_Shape& aBaseShape = aBaseShape_i->impl<TopoDS_Shape>();
+ BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
+ if (aFindPlane.Found() == Standard_True) {
+ Handle(Geom_Plane) aPlane;
+ if (aBaseShape.ShapeType() == TopAbs_FACE || aBaseShape.ShapeType() == TopAbs_SHELL) {
+ TopExp_Explorer anExp(aBaseShape, TopAbs_FACE);
+ const TopoDS_Shape& aFace = anExp.Current();
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(TopoDS::Face(aFace));
+ if(aSurface->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+ Handle(Geom_RectangularTrimmedSurface) aTrimSurface =
+ Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+ aSurface = aTrimSurface->BasisSurface();
+ }
+ if(aSurface->DynamicType() != STANDARD_TYPE(Geom_Plane)) {
+ return;
+ }
+ aPlane = Handle(Geom_Plane)::DownCast(aSurface);
+ } else {
+ aPlane = aFindPlane.Plane();
+ }
+ aDir = aPlane->Axis().Direction();
+ } else {
+ return;
+ }
+
+ // Objects bounds
+ Standard_Real lowBnd, upperBnd;
+ getMinMaxPointsOnLine(aBndObjs, aDir, lowBnd, upperBnd);
+
+ // Base bounds
+ Standard_Real lowBase, upperBase;
+ getMinMaxPointsOnLine(aBndBases, aDir, lowBase, upperBase);
+
+ // ----------.-----.---------.--------------.-----------> theDir
+ // lowBnd lowBase upperBase upperBnd
+
+ double aToSize_i = upperBnd - lowBase;
+ double aFromSize_i = upperBase - lowBnd;
+
+ if (aToSize_i > theToSize) theToSize = aToSize_i;
+ if (aFromSize_i > theFromSize) theFromSize = aFromSize_i;
+ }
+ }
+}
/// \param[in] theShape shape that should be exploded
/// \return list of sub-shapes (vertices, edges, faces, solids)
GEOMALGOAPI_EXPORT static ListOfShape getLowLevelSubShapes(const GeomShapePtr& theShape);
+
+ /// \brief Calculate prism sizes to ensure that it passes through all objects
+ /// \param[in] theObjects objects to be joined/cutted by the prism
+ /// \param[in] theBaseShapes bases of the prism
+ /// \param[in] theDir direction of the prism
+ /// \param[out] theToSize upper offset of the prism
+ /// \param[out] theFromSize lower offset of the prism
+ GEOMALGOAPI_EXPORT static void computeThroughAll(const ListOfShape& theObjects,
+ const ListOfShape& theBaseShapes,
+ const std::shared_ptr<GeomAPI_Dir> theDir,
+ double& theToSize, double& theFromSize);
};
#endif
--- /dev/null
+// Copyright (C) 2014-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_ThroughAll.h"
+
+#include <GeomAlgoAPI_Boolean.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <BRep_Builder.hxx>
+#include <BOPAlgo_BOP.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopExp_Explorer.hxx>
+
+//=================================================================================================
+GeomAlgoAPI_ThroughAll::GeomAlgoAPI_ThroughAll(std::shared_ptr<GeomAlgoAPI_Prism> thePrismAlgo,
+ const ListOfShape& theObjects)
+: GeomAlgoAPI_Boolean(thePrismAlgo->shape(), theObjects, GeomAlgoAPI_Tools::BOOL_CUT)
+{
+ removeEnds(thePrismAlgo);
+}
+
+//=================================================================================================
+void GeomAlgoAPI_ThroughAll::removeEnds(std::shared_ptr<GeomAlgoAPI_Prism> thePrismAlgo)
+{
+ GeomShapePtr aCuttedTool = shape(); // result of BOP Cut (thePrismAlgo->shape() by theObjects)
+
+ // Simplify the result
+ ListOfShape aPieces = GeomAlgoAPI_ShapeTools::getLowLevelSubShapes(aCuttedTool);
+
+ // Get end shapes of Prism
+ const ListOfShape& fromShapes = thePrismAlgo->fromShapes();
+ const ListOfShape& toShapes = thePrismAlgo->toShapes();
+ ListOfShape endShapes (fromShapes);
+ endShapes.insert(endShapes.end(), toShapes.begin(), toShapes.end());
+
+ // Throw away end pieces of cutted tools (containing endShapes)
+ TopTools_ListOfShape listTools;
+ for (ListOfShape::const_iterator
+ anIt = aPieces.begin(); anIt != aPieces.end(); anIt++) {
+ TopoDS_Shape aPiece = (*anIt)->impl<TopoDS_Shape>();
+ bool endPiece = false;
+
+ for (ListOfShape::const_iterator aBaseIt = endShapes.begin();
+ aBaseIt != endShapes.end() && !endPiece; aBaseIt++) {
+ // Check, if the piece contains aBase (one of endShapes)
+ TopoDS_Shape aBase = (*aBaseIt)->impl<TopoDS_Shape>();
+ TopExp_Explorer anExp (aPiece, aBase.ShapeType());
+ for (; anExp.More() && !endPiece; anExp.Next()) {
+ if (anExp.Current().IsSame(aBase))
+ endPiece = true;
+ }
+ }
+
+ if (!endPiece) {
+ listTools.Append(aPiece);
+ }
+ }
+
+ BRep_Builder aBuilder;
+ TopoDS_Compound aCompound;
+ aBuilder.MakeCompound(aCompound);
+ for (TopTools_ListOfShape::Iterator anIt(listTools); anIt.More(); anIt.Next()) {
+ aBuilder.Add(aCompound, anIt.Value());
+ }
+
+ std::shared_ptr<GeomAPI_Shape> aShape (new GeomAPI_Shape());
+ aShape->setImpl(new TopoDS_Shape(aCompound));
+ this->setShape(aShape);
+ this->setDone(true);
+}
--- /dev/null
+// Copyright (C) 2014-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_ThroughAll_H_
+#define GeomAlgoAPI_ThroughAll_H_
+
+#include <GeomAlgoAPI.h>
+#include <GeomAlgoAPI_Boolean.h>
+#include <GeomAlgoAPI_Prism.h>
+//#include <GeomAlgoAPI_Tools.h>
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_ThroughAll
+/// \ingroup DataAlgo
+/// \brief Cuts a prism by all given objects, throw away end pieces
+class GeomAlgoAPI_ThroughAll : public GeomAlgoAPI_Boolean
+{
+public:
+
+ /// Constructor.
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_ThroughAll (std::shared_ptr<GeomAlgoAPI_Prism> thePrismAlgo,
+ const ListOfShape& theObjects);
+
+private:
+ /// Builds resulting shape.
+ void removeEnds (std::shared_ptr<GeomAlgoAPI_Prism> thePrismAlgo);
+};
+
+#endif
#include "GeomAlgoAPI_UnifySameDomain.h"
#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_DFLoader.h>
#include <GeomAlgoAPI_ShapeTools.h>
#include <ShapeUpgrade_UnifySameDomain.hxx>
if (aResult.IsNull()) {
return;
}
+ // take off the compound if it consists of single sub-shape
+ if (aResult.ShapeType() == TopAbs_COMPOUND) {
+ aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
+ }
if (theIsToSimplifyShell && aResult.ShapeType() == TopAbs_SHELL) {
int aNb = 0;
if (!myIsInitialized) {
// create attribute: not initialized by value yet, just zero
myCoords = TDataStd_RealArray::Set(myLab, 0, 2);
+ myIsInitialized = true;
}
}
INCLUDE_DIRECTORIES(
../GeomAPI # only for SWIG
+ ../Events # only for SWIG
../ModelAPI
)
#include <GeomAPI_swig.h>
#include <ModelAPI_swig.h>
+ #include <Events_MessageGroup.h>
#include "GeomDataAPI.h"
#include "GeomDataAPI_Point.h"
GeomValidators_ValueOrder.h
GeomValidators_Intersected.h
GeomValidators_NotSelfIntersected.h
+ GeomValidators_GlobalSelection.h
)
SET(PROJECT_SOURCES
GeomValidators_ValueOrder.cpp
GeomValidators_Intersected.cpp
GeomValidators_NotSelfIntersected.cpp
+ GeomValidators_GlobalSelection.cpp
)
SET(PROJECT_LIBRARIES
break;
}
if (aIt == aResList.cend()) {
- theError = "Error: Feature doesn't creates body.";
+ theError = "Error: Feature doesn't create body.";
return false;
}
}
--- /dev/null
+// Copyright (C) 2014-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 "GeomValidators_GlobalSelection.h"
+
+#include <Events_InfoMessage.h>
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Object.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_ResultBody.h>
+
+bool GeomValidators_GlobalSelection::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ std::string anAttributeType = theAttribute->attributeType();
+ if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
+ AttributeSelectionPtr anAttrSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+ ResultPtr aContext = anAttrSelection->context();
+ if (!aContext.get()) {
+ theError = "Error: Context is empty.";
+ return false;
+ }
+
+ GeomShapePtr aShape = anAttrSelection->value();
+ if (aShape && !aShape->isEqual(aContext->shape())) {
+ theError = "Error: Local selection not allowed.";
+ return false;
+ }
+ } else if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
+ AttributeSelectionListPtr anAttrSelectionList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+
+ // All objects should not be result constructions.
+ for(int anIndex = 0, aSize = anAttrSelectionList->size(); anIndex < aSize; ++anIndex) {
+ AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+ if(!isValid(anAttrSelection, theArguments, theError)) {
+ return false;
+ }
+ }
+ } else {
+// LCOV_EXCL_START
+ theError = "Error: Attribute \"%1\" does not supported by this validator.";
+ theError.arg(anAttributeType);
+ return false;
+// LCOV_EXCL_STOP
+ }
+
+ return true;
+}
--- /dev/null
+// Copyright (C) 2014-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 GeomValidators_GlobalSelection_H
+#define GeomValidators_GlobalSelection_H
+
+#include <GeomValidators.h>
+
+#include <ModelAPI_AttributeValidator.h>
+#include <ModelAPI_Attribute.h>
+
+/**
+ * Check the Selection/SelectionList attribute for result selected.
+ */
+class GeomValidators_GlobalSelection : public ModelAPI_AttributeValidator
+{
+public:
+ /// \return True if the attribute is valid.
+ /// It checks whether the selected object is a full result.
+ /// \param[in] theAttribute an attribute to check
+ /// \param[in] theArguments a filter parameters
+ /// \param[out] theError error message.
+ GEOMVALIDATORS_EXPORT virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
+#endif
#include <GeomValidators_DifferentShapes.h>
#include <GeomValidators_Face.h>
#include <GeomValidators_Finite.h>
+#include <GeomValidators_GlobalSelection.h>
#include <GeomValidators_ShapeType.h>
#include <GeomValidators_ZeroOffset.h>
#include <GeomValidators_FeatureKind.h>
aFactory->registerValidator("GeomValidators_Intersected", new GeomValidators_Intersected);
aFactory->registerValidator("GeomValidators_NotSelfIntersected",
new GeomValidators_NotSelfIntersected);
+ aFactory->registerValidator("GeomValidators_GlobalSelection", new GeomValidators_GlobalSelection);
// Do not register this plugin because it doesn't create features
//ModelAPI_Session::get()->registerPlugin(this);
if(theFeature->string(*anIt)) {
aSelectedMethod = theFeature->string(*anIt)->value();
}
+ if (aSelectedMethod == "ThroughAll") return true;
anIt++;
std::string aCreationMethod = *anIt;
anIt++;
Model_ResultField.h
Model_ResultGroup.h
Model_ResultParameter.h
+ Model_Tools.h
Model_Update.h
Model_Validator.h
)
Model_ResultField.cpp
Model_ResultGroup.cpp
Model_ResultParameter.cpp
+ Model_Tools.cpp
Model_Update.cpp
Model_Validator.cpp
)
../GeomAlgoAPI
../GeomAPI
../ModelGeomAlgo
+ ../ConstructionPlugin
${OpenCASCADE_INCLUDE_DIR}
)
#include <ModelAPI_Events.h>
+#include <BinDrivers_DocumentRetrievalDriver.hxx>
+#include <BinDrivers_DocumentStorageDriver.hxx>
+
IMPLEMENT_STANDARD_RTTIEXT(Model_Application, TDocStd_Application)
static Handle_Model_Application TheApplication = new Model_Application;
// store handle to the application to avoid nullification
static Handle(Model_Application) TheKeepHandle;
TheKeepHandle = this;
+ // additional file format supported
+ static TCollection_ExtendedString THE_DOC_FORMAT("BinShaperPart");
+ static TCollection_ExtendedString THE_FILE_EXT("shaperpart");
+ Handle(PCDM_RetrievalDriver) aReader = new BinDrivers_DocumentRetrievalDriver;
+ Handle(PCDM_StorageDriver) aWriter = new BinDrivers_DocumentStorageDriver;
+ TheKeepHandle->DefineFormat(THE_DOC_FORMAT, "Shaper Part document", THE_FILE_EXT,
+ aReader, aWriter);
}
//=======================================================================
return (myArray.IsNull() || !myArray->IsValid()) ? 0 : myArray->Length();
}
-void Model_AttributeIntArray::setSize(const int theSize)
+void Model_AttributeIntArray::setSize(const int theSize, bool sendUpdated)
{
if (myArray.IsNull() || !myArray->IsValid()) { // create array if it is not done yet
if (theSize != 0) { // if size is zero, nothing to do (null array means there is no array)
myArray = TDataStd_IntegerArray::Set(myLab, 0, theSize - 1);
- owner()->data()->sendAttributeUpdated(this);
+ if (sendUpdated)
+ owner()->data()->sendAttributeUpdated(this);
}
} else { // reset the old array
if (theSize) {
if (theSize != myArray->Length()) { // old data is not kept, a new array is created
Handle(TColStd_HArray1OfInteger) aNewArray = new TColStd_HArray1OfInteger(0, theSize - 1);
myArray->ChangeArray(aNewArray);
- owner()->data()->sendAttributeUpdated(this);
+ if (sendUpdated)
+ owner()->data()->sendAttributeUpdated(this);
}
} else { // size is zero => array must be erased
if (!myArray.IsNull()) {
myArray.Nullify();
myLab.ForgetAttribute(TDataStd_IntegerArray::GetID());
- owner()->data()->sendAttributeUpdated(this);
+ if (sendUpdated)
+ owner()->data()->sendAttributeUpdated(this);
}
}
}
}
void Model_AttributeIntArray::setValue(const int theIndex,
- const int theValue)
+ const int theValue,
+ bool sendUpdated)
{
if (myArray->Value(theIndex) != theValue) {
+ setInitialized();
myArray->SetValue(theIndex, theValue);
- owner()->data()->sendAttributeUpdated(this);
+ if (sendUpdated)
+ owner()->data()->sendAttributeUpdated(this);
}
}
MODEL_EXPORT virtual int size();
/// Sets the new size of the array. The previous data is erased.
- MODEL_EXPORT virtual void setSize(const int theSize);
+ MODEL_EXPORT virtual void setSize(const int theSize,
+ bool sendUpdated = true);
/// Defines the value of the array by index [0; size-1]
MODEL_EXPORT virtual void setValue(const int theIndex,
- const int theValue);
+ const int theValue,
+ bool sendUpdated = true);
/// Returns the value by the index
MODEL_EXPORT virtual int value(const int theIndex);
myIsInitialized = myLab.FindAttribute(TDF_Reference::GetID(), myRef) == Standard_True;
if (!myIsInitialized) {
myRef = TDF_Reference::Set(myLab, myLab); // not initialized references to itself
+ myIsInitialized = true;
} else {
if (owner()) {
std::shared_ptr<Model_Document> aDoc =
std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
{
- if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
+ if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
return std::shared_ptr<GeomAPI_Shape>();
CenterType aType = NOT_CENTER;
std::shared_ptr<GeomAPI_Shape> aResult = internalValue(aType);
bool Model_AttributeSelection::isInitialized()
{
- if (ModelAPI_AttributeSelection::isInitialized()) { // additional checks if it is initialized
- std::shared_ptr<GeomAPI_Shape> aResult;
- if (myRef.isInitialized()) {
- TDF_Label aSelLab = selectionLabel();
- // it is just reference to shape, not sub-shape
- if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) {
- ResultPtr aContext = context();
- return aContext.get() != NULL;
- }
- Handle(TNaming_NamedShape) aSelection;
- if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
- return !aSelection->Get().IsNull();
- } else { // for simple construction element: just shape of this construction element
- if (myRef.value().get())
- return true;
- // check that this is on open of document, so, results are not initialized yet
- TDF_Label aRefLab = myRef.myRef->Get();
- if (aRefLab.IsNull() || !owner().get())
- return false;
- std::shared_ptr<Model_Document> aMyDoc =
- std::dynamic_pointer_cast<Model_Document>(owner()->document());
- if (!aMyDoc.get())
- return false;
- // check at least the feature exists
- return aMyDoc->featureByLab(aRefLab).get() != NULL;
- }
+ if (myRef.isInitialized()) {
+ TDF_Label aSelLab = selectionLabel();
+ // it is just reference to shape, not sub-shape
+ if (aSelLab.IsAttribute(kSIMPLE_REF_ID) || aSelLab.IsAttribute(kPART_REF_ID)) {
+ ResultPtr aContext = context();
+ return aContext.get() != NULL;
+ }
+ Handle(TNaming_NamedShape) aSelection;
+ if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
+ return !aSelection->Get().IsNull();
+ } else { // for simple construction element: just shape of this construction element
+ if (myRef.value().get())
+ return true;
+ // check that this is on open of document, so, results are not initialized yet
+ TDF_Label aRefLab = myRef.myRef->Get();
+ if (aRefLab.IsNull() || !owner().get())
+ return false;
+ std::shared_ptr<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ if (!aMyDoc.get())
+ return false;
+ // check at least the feature exists
+ return aMyDoc->featureByLab(aRefLab).get() != NULL;
}
}
return false;
ResultPtr Model_AttributeSelection::context()
{
- if (!ModelAPI_AttributeSelection::isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
+ if (!myRef.isInitialized() && !myTmpContext.get() && !myTmpSubShape.get())
return ResultPtr();
if (myTmpContext.get() || myTmpSubShape.get()) {
static TDF_Label anEmpty;
return anEmpty;
}
+
+void Model_AttributeSelection::reset()
+{
+ ModelAPI_AttributeSelection::reset();
+ myRef.reset();
+}
/// Makes the current local selection becomes all sub-shapes with same base geometry.
MODEL_EXPORT virtual void combineGeometrical();
+ /// Resets attribute to deafult state
+ MODEL_EXPORT virtual void reset();
+
protected:
/// Objects are created for features automatically
MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel);
#include <Model_AttributeTables.h>
#include <Model_Events.h>
#include <Model_Expression.h>
+#include <Model_Tools.h>
+#include <Model_Validator.h>
+
#include <ModelAPI_Feature.h>
#include <ModelAPI_Result.h>
#include <ModelAPI_ResultParameter.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Tools.h>
-#include <Model_Validator.h>
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
#include <TDataStd_Name.hxx>
#include <TDataStd_AsciiString.hxx>
-#include <TDataStd_IntegerArray.hxx>
#include <TDataStd_UAttribute.hxx>
-#include <TDF_AttributeIterator.hxx>
-#include <TDF_ChildIterator.hxx>
-#include <TDF_RelocationTable.hxx>
#include <TDF_ChildIDIterator.hxx>
-#include <TColStd_HArray1OfByte.hxx>
#include <string>
}
} else {
// trim: need to redisplay or set color in the python script
- if (myObject && (theAttr->attributeType() == "Point2D" || theAttr->id() == "Color")) {
+ if (myObject && (theAttr->attributeType() == "Point2D" || theAttr->id() == "Color" ||
+ theAttr->id() == "Transparency" || theAttr->id() == "Deflection")) {
static const Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
ModelAPI_EventCreator::get()->sendUpdated(myObject, anEvent);
}
}
}
-/// makes copy of all attributes on the given label and all sub-labels
-static void copyAttrs(TDF_Label theSource, TDF_Label theDestination) {
- TDF_AttributeIterator anAttrIter(theSource);
- for(; anAttrIter.More(); anAttrIter.Next()) {
- Handle(TDF_Attribute) aTargetAttr;
- if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
- // create a new attribute if not yet exists in the destination
- aTargetAttr = anAttrIter.Value()->NewEmpty();
- theDestination.AddAttribute(aTargetAttr);
- }
- // no special relocation, empty map, but self-relocation is on: copy references w/o changes
- Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable(Standard_True);
- anAttrIter.Value()->Paste(aTargetAttr, aRelocTable);
- // an exception: if a source reference refers itself, a copy must also refer itself
- if (aTargetAttr->ID() == TDF_Reference::GetID()) {
- Handle(TDF_Reference) aTargetRef = Handle(TDF_Reference)::DownCast(aTargetAttr);
- if (aTargetRef->Get().IsEqual(anAttrIter.Value()->Label()))
- aTargetRef->Set(aTargetRef->Label());
- }
- }
- // copy the sub-labels content
- TDF_ChildIterator aSubLabsIter(theSource);
- for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
- copyAttrs(aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()));
- }
-}
-
void Model_Data::copyTo(std::shared_ptr<ModelAPI_Data> theTarget)
{
TDF_Label aTargetRoot = std::dynamic_pointer_cast<Model_Data>(theTarget)->label();
- copyAttrs(myLab, aTargetRoot);
+ Model_Tools::copyAttrs(myLab, aTargetRoot);
// reinitialize Model_Attributes by TDF_Attributes set
std::shared_ptr<Model_Data> aTData = std::dynamic_pointer_cast<Model_Data>(theTarget);
aTData->myAttrs.clear();
friend class Model_SelectionNaming;
friend class Model_ResultConstruction;
friend class Model_ResultBody;
+ friend class Model_Tools;
public:
/// The simplest constructor. "setLabel" must be called just after to initialize correctly.
#include <Model_Application.h>
#include <Model_Session.h>
#include <Model_Events.h>
+#include <Model_Tools.h>
#include <ModelAPI_ResultPart.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_CompositeFeature.h>
#include <TNaming_Iterator.hxx>
#include <TNaming_NamedShape.hxx>
#include <TNaming_Tool.hxx>
-#include<TNaming_OldShapeIterator.hxx>
+#include <TNaming_OldShapeIterator.hxx>
#include <TopTools_DataMapOfShapeShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Shape.hxx>
+#include <OSD_Directory.hxx>
#include <OSD_File.hxx>
#include <OSD_Path.hxx>
+#include <OSD_Protection.hxx>
#include <CDF_Session.hxx>
#include <CDF_Directory.hxx>
+#include <UTL.hxx>
#include <climits>
#ifndef WIN32
}
// LCOV_EXCL_STOP
-bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis)
+static bool loadDocument(Handle(Model_Application) theApp,
+ Handle(TDocStd_Document)& theDoc,
+ const TCollection_ExtendedString& theFilename)
{
- Handle(Model_Application) anApp = Model_Application::getApplication();
- if (isRoot()) {
- anApp->setLoadPath(theDirName);
- }
- TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName));
- PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
- Handle(TDocStd_Document) aLoaded;
+ PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus)-1;
try {
- aStatus = anApp->Open(aPath, aLoaded);
+ aStatus = theApp->Open(theFilename, theDoc);
} catch (Standard_Failure const& anException) {
Events_InfoMessage("Model_Document",
"Exception in opening of document: %1").arg(anException.GetMessageString()).send();
return false;
}
- bool isError = aStatus != PCDM_RS_OK;
- if (isError) {
+ bool isOk = aStatus == PCDM_RS_OK;
+ if (!isOk) {
// LCOV_EXCL_START
switch (aStatus) {
case PCDM_RS_UnknownDocument:
}
// LCOV_EXCL_STOP
}
+ return isOk;
+}
+
+bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis)
+{
+ Handle(Model_Application) anApp = Model_Application::getApplication();
+ if (isRoot()) {
+ anApp->setLoadPath(theDirName);
+ }
+ TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName));
+ Handle(TDocStd_Document) aLoaded;
+ bool isOk = loadDocument(anApp, aLoaded, aPath);
+
std::shared_ptr<Model_Session> aSession =
std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
- if (!isError) {
+ if (isOk) {
myDoc = aLoaded;
myDoc->SetUndoLimit(UNDO_LIMIT);
} else { // open failed, but new document was created to work with it: inform the model
aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
}
- return !isError;
+ return isOk;
+}
+
+bool Model_Document::importPart(const char* theFileName,
+ std::list<std::shared_ptr<ModelAPI_Feature> >& theImported,
+ bool theCheckOnly)
+{
+ Handle(Model_Application) anApp = Model_Application::getApplication();
+ TCollection_ExtendedString aFormat;
+ if (!anApp->Format(theFileName, aFormat))
+ return false;
+
+ Handle(TDocStd_Document) aTempDoc;
+ bool isOk = loadDocument(anApp, aTempDoc, theFileName);
+
+ if (isOk && theCheckOnly) {
+ // verify all features are applicable for the current document type (e.g. PartSet)
+ std::shared_ptr<Model_Session> aSession =
+ std::dynamic_pointer_cast<Model_Session>(ModelAPI_Session::get());
+ for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More() && isOk; anIt.Next()) {
+ TDF_Label aCurrentLab = anIt.Value();
+ Handle(TDataStd_Comment) aFeatureID;
+ TDF_Label aNewFeatuerLab;
+ if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) {
+ TCollection_AsciiString anID(aFeatureID->Get());
+ std::string aFeatureKind(anID.ToCString());
+ if (aSession->myPlugins.find(aFeatureKind) != aSession->myPlugins.end()) {
+ std::string& aDocKind = aSession->myPlugins[aFeatureKind].second;
+ isOk = aDocKind.empty() || aDocKind == kind();
+ }
+ }
+ }
+ }
+
+ if (isOk && !theCheckOnly) {
+ // copy features from the temporary document to the current
+ Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable();
+ TDF_LabelList anAllNewFeatures;
+ // Perform the copying twice for correct references:
+ // 1. copy labels hierarchy and fill the relocation table
+ TDF_Label aMain = myDoc->Main();
+ for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) {
+ TDF_Label aCurrentLab = anIt.Value();
+ Handle(TDataStd_Comment) aFeatureID;
+ TDF_Label aNewFeatuerLab;
+ if (aCurrentLab.FindAttribute(TDataStd_Comment::GetID(), aFeatureID)) {
+ TCollection_AsciiString anID(aFeatureID->Get());
+ FeaturePtr aNewFeature = addFeature(anID.ToCString());
+ std::shared_ptr<Model_Data> aData =
+ std::dynamic_pointer_cast<Model_Data>(aNewFeature->data());
+ aNewFeatuerLab = aData->label().Father();
+ Model_Tools::copyLabels(aCurrentLab, aNewFeatuerLab, aRelocTable);
+ theImported.push_back(aNewFeature);
+ }
+ anAllNewFeatures.Append(aNewFeatuerLab);
+ }
+ // 2. copy attributes
+ std::set<TCollection_AsciiString> aCoordinateLabels;
+ Model_Tools::labelsOfCoordinates(aCoordinateLabels, aRelocTable);
+ TDF_ListIteratorOfLabelList aNewIt(anAllNewFeatures);
+ for (TDF_ChildIterator anIt(aTempDoc->Main()); anIt.More(); anIt.Next()) {
+ TDF_Label aCurrentLab = anIt.Value();
+ TDF_Label aFeatureLab = aNewIt.Value();
+ if (aFeatureLab.IsNull())
+ anAllNewFeatures.Remove(aNewIt);
+ else {
+ Model_Tools::copyAttrsAndKeepRefsToCoordinates(
+ aCurrentLab, aFeatureLab, aCoordinateLabels, aRelocTable);
+ aNewIt.Next();
+ }
+ }
+
+ myObjs->synchronizeFeatures(anAllNewFeatures, true, false, false, true);
+ }
+
+ if (anApp->CanClose(aTempDoc) == CDM_CCS_OK)
+ anApp->Close(aTempDoc);
+ return isOk;
+}
+
+static bool saveDocument(Handle(Model_Application) theApp,
+ Handle(TDocStd_Document) theDoc,
+ const TCollection_ExtendedString& theFilename)
+{
+ PCDM_StoreStatus aStatus;
+ try {
+ // create the directory to save the document
+ OSD_Path aPathToFile = UTL::Path(theFilename);
+ aPathToFile.SetName("");
+ aPathToFile.SetExtension("");
+ OSD_Directory aBaseDir(aPathToFile);
+ if (aPathToFile.TrekLength() != 0 && !aBaseDir.Exists())
+ aBaseDir.Build(OSD_Protection());
+ // save the document
+ aStatus = theApp->SaveAs(theDoc, theFilename);
+ }
+ catch (Standard_Failure const& anException) {
+ Events_InfoMessage("Model_Document",
+ "Exception in saving of document: %1").arg(anException.GetMessageString()).send();
+ return false;
+ }
+ bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj;
+ if (!isDone) {
+ switch (aStatus) {
+ case PCDM_SS_DriverFailure:
+ Events_InfoMessage("Model_Document",
+ "Can not save document: save driver-library failure").send();
+ break;
+ case PCDM_SS_WriteFailure:
+ Events_InfoMessage("Model_Document", "Can not save document: file writing failure").send();
+ break;
+ case PCDM_SS_Failure:
+ default:
+ Events_InfoMessage("Model_Document", "Can not save document").send();
+ break;
+ }
+ }
+ return isDone;
}
bool Model_Document::save(
}
// filename in the dir is id of document inside of the given directory
TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName));
- PCDM_StoreStatus aStatus;
- try {
- aStatus = anApp->SaveAs(myDoc, aPath);
- } catch (Standard_Failure const& anException) {
- Events_InfoMessage("Model_Document",
- "Exception in saving of document: %1").arg(anException.GetMessageString()).send();
- if (aWasCurrent.get()) { // return the current feature to the initial position
- setCurrentFeature(aWasCurrent, false);
- aSession->setCheckTransactions(true);
- }
- return false;
- }
- bool isDone = aStatus == PCDM_SS_OK || aStatus == PCDM_SS_No_Obj;
- if (!isDone) {
- switch (aStatus) {
- case PCDM_SS_DriverFailure:
- Events_InfoMessage("Model_Document",
- "Can not save document: save driver-library failure").send();
- break;
- case PCDM_SS_WriteFailure:
- Events_InfoMessage("Model_Document", "Can not save document: file writing failure").send();
- break;
- case PCDM_SS_Failure:
- default:
- Events_InfoMessage("Model_Document", "Can not save document").send();
- break;
- }
- }
+ bool isDone = saveDocument(anApp, myDoc, aPath);
if (aWasCurrent.get()) { // return the current feature to the initial position
setCurrentFeature(aWasCurrent, false);
return isDone;
}
+bool Model_Document::save(const char* theFilename,
+ const std::list<FeaturePtr>& theExportFeatures) const
+{
+ Handle(Model_Application) anApp = Model_Application::getApplication();
+ TCollection_ExtendedString aFormat;
+ if (!anApp->Format(theFilename, aFormat))
+ return false;
+
+ Handle(TDocStd_Document) aTempDoc = new TDocStd_Document(aFormat);
+ TDF_Label aMain = aTempDoc->Main();
+
+ Handle(TDF_RelocationTable) aRelocTable = new TDF_RelocationTable();
+ std::list<FeaturePtr>::const_iterator anIt = theExportFeatures.begin();
+ // Perform the copying twice for correct references:
+ // 1. copy labels hierarchy and fill the relocation table
+ for (; anIt != theExportFeatures.end(); ++anIt) {
+ TDF_Label aFeatureLab = aMain.NewChild();
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>((*anIt)->data());
+ Model_Tools::copyLabels(aData->label().Father(), aFeatureLab, aRelocTable);
+ }
+ // 2. copy attributes
+ std::set<TCollection_AsciiString> aCoordinateLabels;
+ Model_Tools::labelsOfCoordinates(aCoordinateLabels, aRelocTable);
+ TDF_ChildIterator aChildIt(aMain);
+ for (anIt = theExportFeatures.begin(); anIt != theExportFeatures.end(); ++anIt) {
+ TDF_Label aFeatureLab = aChildIt.Value();
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>((*anIt)->data());
+ Model_Tools::copyAttrsAndKeepRefsToCoordinates(
+ aData->label().Father(), aFeatureLab, aCoordinateLabels, aRelocTable);
+ aChildIt.Next();
+ }
+
+ bool isDone = saveDocument(anApp, aTempDoc, theFilename);
+ if (aTempDoc->CanClose() == CDM_CCS_OK)
+ aTempDoc->Close();
+ return isDone;
+}
+
void Model_Document::close(const bool theForever)
{
std::shared_ptr<ModelAPI_Session> aPM = Model_Session::get();
return isSub(theMain, aParent);
}
-void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis)
+void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis, const bool theSplit)
{
bool aCurrentUp = theMoved == currentFeature(false);
if (aCurrentUp) {
}
myObjs->moveFeature(theMoved, anAfterThisSub);
+
+ if (theSplit) { // split the group into sub-features
+ theMoved->customAction("split");
+ }
+
if (aCurrentUp) { // make the moved feature enabled or disabled due to the real status
setCurrentFeature(currentFeature(false), false);
} else if (theAfterThis == currentFeature(false) || anAfterThisSub == currentFeature(false)) {
// must be after move to make enabled all features which are before theMoved
setCurrentFeature(theMoved, true);
}
+
+ if (theSplit) { // split the group into sub-features
+ theMoved->customAction("split");
+ }
}
void Model_Document::updateHistory(const std::shared_ptr<ModelAPI_Object> theObject)
MODEL_EXPORT virtual bool load(
const char* theDirName, const char* theFileName, DocumentPtr theThis);
+ //! Loads the OCAF document from the file into the current document.
+ //! All the features are added after the active feature.
+ //! \param theFileName name of the file to import
+ //! \param theImported list of features imported from the file
+ //! \param theCheckOnly verify the document does not contain unappropriate features
+ //! (useful for import to PartSet), but do not import it
+ //! \returns true if file was loaded successfully
+ MODEL_EXPORT virtual bool importPart(const char* theFileName,
+ std::list<std::shared_ptr<ModelAPI_Feature> >& theImported,
+ bool theCheckOnly = false);
+
//! Saves the OCAF document to the file.
//! \param theDirName directory where the document will be saved
//! \param theFileName a name of the document file to store
MODEL_EXPORT virtual bool save(
const char* theDirName, const char* theFileName, std::list<std::string>& theResults);
+ //! Export the list of features to the file
+ //! \param theFilename path to save the file
+ //! \param theExportFeatures list of features to export
+ MODEL_EXPORT virtual bool save(const char* theFilename,
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theExportFeatures) const;
+
//! Removes document data
//! \param theForever if it is false, document is just hidden
//! (to keep possibility make it back on Undo/Redo)
MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature);
//! Moves the feature to make it after the given one in the history.
- MODEL_EXPORT virtual void moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis);
+ MODEL_EXPORT virtual void moveFeature(
+ FeaturePtr theMoved, FeaturePtr theAfterThis, const bool theSplit = false);
//! Returns the first found object in the group by the object name
//! \param theGroupID group that contains an object
--- /dev/null
+// Copyright (C) 2014-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 <Model_Tools.h>
+#include <Model_Data.h>
+
+#include <ModelAPI_Document.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Session.h>
+
+#include <ConstructionPlugin_Axis.h>
+#include <ConstructionPlugin_Plane.h>
+#include <ConstructionPlugin_Point.h>
+
+#include <Standard_GUID.hxx>
+
+#include <TDataStd_Comment.hxx>
+#include <TDataStd_AsciiString.hxx>
+
+#include <TDF_AttributeIterator.hxx>
+#include <TDF_ChildIterator.hxx>
+#include <TDF_Reference.hxx>
+#include <TDF_RelocationTable.hxx>
+#include <TDF_Tool.hxx>
+
+void Model_Tools::copyLabels(TDF_Label theSource, TDF_Label theDestination,
+ Handle(TDF_RelocationTable) theRelocTable)
+{
+ theRelocTable->SetRelocation(theSource, theDestination);
+ // copy the sub-labels hierarchy
+ TDF_ChildIterator aSubLabsIter(theSource);
+ for (; aSubLabsIter.More(); aSubLabsIter.Next()) {
+ copyLabels(aSubLabsIter.Value(),
+ theDestination.FindChild(aSubLabsIter.Value().Tag()),
+ theRelocTable);
+ }
+}
+
+void Model_Tools::copyAttrs(TDF_Label theSource, TDF_Label theDestination,
+ Handle(TDF_RelocationTable) theRelocTable)
+{
+ TDF_AttributeIterator anAttrIter(theSource);
+ for(; anAttrIter.More(); anAttrIter.Next()) {
+ Handle(TDF_Attribute) aTargetAttr;
+ if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
+ // create a new attribute if not yet exists in the destination
+ aTargetAttr = anAttrIter.Value()->NewEmpty();
+ theDestination.AddAttribute(aTargetAttr);
+ }
+ // no special relocation, empty map, but self-relocation is on: copy references w/o changes
+ Handle(TDF_RelocationTable) aRelocTable =
+ theRelocTable.IsNull() ? new TDF_RelocationTable(Standard_True) : theRelocTable;
+ anAttrIter.Value()->Paste(aTargetAttr, aRelocTable);
+ // an exception: if a source reference refers itself, a copy must also refer itself
+ if (aTargetAttr->ID() == TDF_Reference::GetID()) {
+ Handle(TDF_Reference) aTargetRef = Handle(TDF_Reference)::DownCast(aTargetAttr);
+ if (aTargetRef->Get().IsEqual(anAttrIter.Value()->Label()))
+ aTargetRef->Set(aTargetRef->Label());
+ }
+ }
+ // copy the sub-labels content
+ TDF_ChildIterator aSubLabsIter(theSource);
+ for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
+ copyAttrs(aSubLabsIter.Value(),
+ theDestination.FindChild(aSubLabsIter.Value().Tag()),
+ theRelocTable);
+ }
+}
+
+static TCollection_AsciiString labelToString(TDF_Label theLabel)
+{
+ TCollection_AsciiString aLabString;
+ TDF_Tool::Entry(theLabel, aLabString);
+ return aLabString;
+}
+
+static void makeExternalReference(TDF_Label theDestination, TDF_Label theReferred)
+{
+ Handle(TDF_Attribute) aReference, aComment, aString;
+ theDestination.FindAttribute(TDF_Reference::GetID(), aReference);
+ // create new attributes if not yet exists in the destination
+ if (!theDestination.FindAttribute(TDataStd_Comment::GetID(), aComment)) {
+ aComment = new TDataStd_Comment;
+ theDestination.AddAttribute(aComment);
+ }
+ if (!theDestination.FindAttribute(TDataStd_AsciiString::GetID(), aString)) {
+ aString = new TDataStd_AsciiString;
+ theDestination.AddAttribute(aString);
+ }
+ // reference to itself
+ Handle(TDF_Reference)::DownCast(aReference)->Set(theDestination, theDestination);
+ // ID of the document
+ std::ostringstream aDocIdStr;
+ aDocIdStr << ModelAPI_Session::get()->moduleDocument()->id();
+ Handle(TDataStd_Comment)::DownCast(aComment)->Set(aDocIdStr.str().c_str());
+ // value of referred label
+ Handle(TDataStd_AsciiString)::DownCast(aString)->Set(labelToString(theReferred));
+}
+
+void Model_Tools::copyAttrsAndKeepRefsToCoordinates(
+ TDF_Label theSource,
+ TDF_Label theDestination,
+ const std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable)
+{
+ TDF_AttributeIterator anAttrIter(theSource);
+ for(; anAttrIter.More(); anAttrIter.Next()) {
+ Handle(TDF_Attribute) aTargetAttr;
+ if (!theDestination.FindAttribute(anAttrIter.Value()->ID(), aTargetAttr)) {
+ // create a new attribute if not yet exists in the destination
+ aTargetAttr = anAttrIter.Value()->NewEmpty();
+ theDestination.AddAttribute(aTargetAttr);
+ }
+ anAttrIter.Value()->Paste(aTargetAttr, theRelocTable);
+ if (aTargetAttr->ID() == TDF_Reference::GetID()) {
+ Handle(TDF_Reference) aTargetRef = Handle(TDF_Reference)::DownCast(aTargetAttr);
+ if (aTargetRef->Get().IsNull()) {
+ // may be refer to a cartesian coordinate entity
+ Handle(TDF_Reference) aSourceRef = Handle(TDF_Reference)::DownCast(anAttrIter.Value());
+ if (!aSourceRef.IsNull() && !aSourceRef->Get().IsNull()) {
+ std::set<TCollection_AsciiString>::const_iterator aFound =
+ theCoordinateLabels.find(labelToString(aSourceRef->Get()));
+ if (aFound != theCoordinateLabels.end())
+ makeExternalReference(theDestination, aSourceRef->Get());
+ }
+ }
+ else if (aTargetRef->Get().IsEqual(anAttrIter.Value()->Label())) {
+ // a source reference refers itself, a copy must also refer itself
+ aTargetRef->Set(aTargetRef->Label());
+ }
+ }
+ }
+ // copy the sub-labels content
+ TDF_ChildIterator aSubLabsIter(theSource);
+ for(; aSubLabsIter.More(); aSubLabsIter.Next()) {
+ copyAttrsAndKeepRefsToCoordinates(
+ aSubLabsIter.Value(), theDestination.FindChild(aSubLabsIter.Value().Tag()),
+ theCoordinateLabels, theRelocTable);
+ }
+}
+
+void Model_Tools::labelsOfCoordinates(std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable)
+{
+ DocumentPtr aPartSet = ModelAPI_Session::get()->moduleDocument();
+ std::list<FeaturePtr> aFeatures = aPartSet->allFeatures();
+ for (std::list<FeaturePtr>::iterator aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) {
+ FeaturePtr aCurFeat = *aFIt;
+ if (!aCurFeat->isInHistory() &&
+ (aCurFeat->getKind() == ConstructionPlugin_Point::ID() ||
+ aCurFeat->getKind() == ConstructionPlugin_Axis::ID() ||
+ aCurFeat->getKind() == ConstructionPlugin_Plane::ID())) {
+ ResultPtr aResult = aCurFeat->lastResult();
+ if (aResult) {
+ std::shared_ptr<Model_Data> aResData =
+ std::dynamic_pointer_cast<Model_Data>(aResult->data());
+ TDF_Label aLab = aResData->label().Father();
+ theCoordinateLabels.insert(labelToString(aLab));
+ // set relocation to empty, references will be set correctly while copying attributes
+ theRelocTable->SetRelocation(aLab, TDF_Label());
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2014-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 Model_Tools_H_
+#define Model_Tools_H_
+
+#include <Model.h>
+
+#include <TDF_Label.hxx>
+#include <TDF_RelocationTable.hxx>
+
+#include <memory>
+#include <set>
+
+/// A collection of methods useful for different parts of data model.
+class Model_Tools
+{
+public:
+ /// makes copy of label and all its sub-labels without copying the attributes;
+ /// and feel the relocation table
+ static void copyLabels(TDF_Label theSource, TDF_Label theDestination,
+ Handle(TDF_RelocationTable) theRelocTable);
+
+ /// makes copy of all attributes on the given label and all sub-labels
+ static void copyAttrs(TDF_Label theSource, TDF_Label theDestination,
+ Handle(TDF_RelocationTable) theRelocTable = Handle(TDF_RelocationTable)());
+
+ /// makes copy of all attributes on the given label and all sub-labels,
+ /// but keep references to the Origin, coordinate axes and coordinate planes
+ static void copyAttrsAndKeepRefsToCoordinates(TDF_Label theSource, TDF_Label theDestination,
+ const std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable);
+
+ /// collect labels of coordinate planes, axes, and origin
+ static void labelsOfCoordinates(
+ std::set<TCollection_AsciiString>& theCoordinateLabels,
+ Handle(TDF_RelocationTable) theRelocTable);
+};
+
+#endif
Config
GeomAPI
)
-SET(CMAKE_SWIG_FLAGS -threads -w325,321,362,383,302,403,473)
+SET(CMAKE_SWIG_FLAGS -threads -w325,321,362,383,302,403,451,473)
ADD_DEFINITIONS(-DMODELAPI_EXPORTS)
ADD_LIBRARY(ModelAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
// import other modules
%import "GeomAPI.i"
+%import "Events.i"
// to avoid error on this
#define MODELAPI_EXPORT
%shared_ptr(ModelAPI_ResultField)
%shared_ptr(ModelAPI_ResultParameter)
%shared_ptr(ModelAPI_ResultCompSolid)
+%shared_ptr(ModelAPI_ObjectUpdatedMessage)
%typecheck(SWIG_TYPECHECK_POINTER) const ModelAPI_AttributeTables::Value {
$1 = (PyFloat_Check($input) || PyLong_Check($input) || PyUnicode_Check($input) || PyBool_Check($input)) ? 1 : 0;
// all supported interfaces
%include "ModelAPI_Entity.h"
+%include "ModelAPI_Events.h"
%include "ModelAPI_Document.h"
%include "ModelAPI_Session.h"
%include "ModelAPI_Plugin.h"
// std::set -> []
%template(AttributeSet) std::set<std::shared_ptr<ModelAPI_Attribute> >;
%template(FeatureSet) std::set<std::shared_ptr<ModelAPI_Feature> >;
+%template(ObjectSet) std::set<std::shared_ptr<ModelAPI_Object> >;
// std::dynamic_pointer_cast
template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr<T2> theObject);
%template(modelAPI_ResultGroup) shared_ptr_cast<ModelAPI_ResultGroup, ModelAPI_Result>;
%template(modelAPI_ResultField) shared_ptr_cast<ModelAPI_ResultField, ModelAPI_Result>;
+%template(messageToUpdatedMessage) shared_ptr_cast<ModelAPI_ObjectUpdatedMessage, Events_Message>;
+
// Attribute casts
%template(modelAPI_AttributeDocRef) shared_ptr_cast<ModelAPI_AttributeDocRef, ModelAPI_Attribute>;
%template(modelAPI_AttributeDouble) shared_ptr_cast<ModelAPI_AttributeDouble, ModelAPI_Attribute>;
MODELAPI_EXPORT virtual int size() = 0;
/// Sets the new size of the array. The previous data is erased.
- MODELAPI_EXPORT virtual void setSize(const int theSize) = 0;
+ MODELAPI_EXPORT virtual void setSize(const int theSize,
+ bool sendUpdated = true) = 0;
/// Defines the value of the array by index [0; size-1]
MODELAPI_EXPORT virtual void setValue(const int theIndex,
- const int theValue) = 0;
+ const int theValue,
+ bool sendUpdated = true) = 0;
/// Returns the value by the index
MODELAPI_EXPORT virtual int value(const int theIndex) = 0;
//! Moves the feature to make it after the given one in the history.
virtual void moveFeature(std::shared_ptr<ModelAPI_Feature> theMoved,
- std::shared_ptr<ModelAPI_Feature> theAfterThis) = 0;
+ std::shared_ptr<ModelAPI_Feature> theAfterThis,
+ const bool theSplit = false) = 0;
///! Returns the id of the document
virtual const int id() const = 0;
MODELAPI_EXPORT virtual std::shared_ptr<ModelAPI_Feature> nextFeature(
std::shared_ptr<ModelAPI_Feature> theCurrent, const bool theReverse = false) const = 0;
+ /// Loads the OCAF document from the file into the current document.
+ /// All the features are added after the active feature.
+ /// \param theFileName name of the file to import
+ /// \param theImported list of features imported from the file
+ /// \param theCheckOnly verify the document does not contain unappropriate features
+ /// (useful for import to PartSet), but do not import it
+ /// \returns true if file was loaded successfully
+ MODELAPI_EXPORT virtual bool importPart(const char* theFileName,
+ std::list<std::shared_ptr<ModelAPI_Feature> >& theImported,
+ bool theCheckOnly = false) = 0;
+
+ /// Export the list of features to the file
+ /// \param theFilename path to save the file
+ /// \param theExportFeatures list of features to export
+ MODELAPI_EXPORT virtual bool save(const char* theFilename,
+ const std::list<std::shared_ptr<ModelAPI_Feature> >& theExportFeatures) const = 0;
+
protected:
//! Only for SWIG wrapping it is here
MODELAPI_EXPORT ModelAPI_Document();
/// Event ID that the sketch is prepared and all grouped messages for the solver may be flushed
static const char * EVENT_SKETCH_PREPARED = "SketchPrepared";
+/// Event ID that provides a request for list of non-fixed objects necessary for DoF = 0
+static const char * EVENT_GET_DOF_OBJECTS = "GetDoFObjects";
+
+/// Event ID that provides a request for list of non-fixed objects necessary for DoF = 0
+static const char * EVENT_DOF_OBJECTS = "DoFObjects";
+
+/// Event ID that requests updates visual attributes for presentations
+static const char * EVENT_VISUAL_ATTRIBUTES = "UpdateVisualAttributes";
+
/// Message that feature was changed (used for Object Browser update): moved, updated and deleted
class MODELAPI_EXPORT ModelAPI_ObjectUpdatedMessage : public Events_MessageGroup
{
#include <ModelAPI_ResultPart.h>
#include <ModelAPI_AttributeDocRef.h>
#include <ModelAPI_Validator.h>
+#include <ModelAPI_AttributeIntArray.h>
#include <list>
#include <map>
#include <iostream>
}
}
+// used by GUI only
+// LCOV_EXCL_START
+double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult)
+{
+ double aDeflection = -1;
+ // get deflection from the attribute of the result
+ if (theResult.get() != NULL &&
+ theResult->data()->attribute(ModelAPI_Result::DEFLECTION_ID()).get() != NULL) {
+ AttributeDoublePtr aDoubleAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
+ if (aDoubleAttr.get() && aDoubleAttr->isInitialized()) {
+ double aValue = aDoubleAttr->value();
+ if (aValue > 0) /// zero value should not be used as a deflection(previous studies)
+ aDeflection = aDoubleAttr->value();
+ }
+ }
+ return aDeflection;
+}
+
+
+void getColor(const std::shared_ptr<ModelAPI_Result>& theResult, std::vector<int>& theColor)
+{
+ theColor.clear();
+ // get color from the attribute of the result
+ if (theResult.get() != NULL &&
+ theResult->data()->attribute(ModelAPI_Result::COLOR_ID()).get() != NULL) {
+ AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+ if (aColorAttr.get() && aColorAttr->size()) {
+ theColor.push_back(aColorAttr->value(0));
+ theColor.push_back(aColorAttr->value(1));
+ theColor.push_back(aColorAttr->value(2));
+ }
+ }
+}
+
+double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult)
+{
+ double aTransparency = -1;
+ // get transparency from the attribute of the result
+ if (theResult.get() != NULL &&
+ theResult->data()->attribute(ModelAPI_Result::TRANSPARENCY_ID()).get() != NULL) {
+ AttributeDoublePtr aDoubleAttr = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
+ if (aDoubleAttr.get() && aDoubleAttr->isInitialized()) {
+ aTransparency = aDoubleAttr->value();
+ }
+ }
+ return aTransparency;
+}
+// LCOV_EXCL_STOP
+
+void copyVisualizationAttrs(
+ std::shared_ptr<ModelAPI_Result> theSource, std::shared_ptr<ModelAPI_Result> theDest)
+{
+ // color
+ AttributeIntArrayPtr aSourceColor = theSource->data()->intArray(ModelAPI_Result::COLOR_ID());
+ if (aSourceColor.get() && aSourceColor->isInitialized() && aSourceColor->size()) {
+ AttributeIntArrayPtr aDestColor = theDest->data()->intArray(ModelAPI_Result::COLOR_ID());
+ if (aDestColor.get()) {
+ aDestColor->setSize(aSourceColor->size());
+ for(int a = 0; a < aSourceColor->size(); a++)
+ aDestColor->setValue(a, aSourceColor->value(a));
+ }
+ }
+ // deflection
+ AttributeDoublePtr aSourceDefl = theSource->data()->real(ModelAPI_Result::DEFLECTION_ID());
+ if (aSourceDefl.get() && aSourceDefl->isInitialized()) {
+ AttributeDoublePtr aDestDefl = theDest->data()->real(ModelAPI_Result::DEFLECTION_ID());
+ if (aDestDefl.get()) {
+ aDestDefl->setValue(aSourceDefl->value());
+ }
+ }
+ // transparency
+ AttributeDoublePtr aSourceTransp = theSource->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
+ if (aSourceTransp.get() && aSourceTransp->isInitialized()) {
+ AttributeDoublePtr aDestTransp = theDest->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
+ if (aDestTransp.get()) {
+ aDestTransp->setValue(aSourceTransp->value());
+ }
+ }
+}
+
} // namespace ModelAPI_Tools
/*! Creates a remove result features with the given results
*/
MODELAPI_EXPORT void removeResults(const std::list<std::shared_ptr<ModelAPI_Result> >& theResults);
+
+/*! Returns current deflection in the given result
+* \param theResult a result object
+* \return a deflection value or -1 if it was not defined
+*/
+MODELAPI_EXPORT double getDeflection(const std::shared_ptr<ModelAPI_Result>& theResult);
+
+/*! Returns current color of the current result
+* \param[in] theResult a result object
+* \param[out] theColor a color values if it is defined
+*/
+MODELAPI_EXPORT void getColor(const std::shared_ptr<ModelAPI_Result>& theResult,
+ std::vector<int>& theColor);
+
+/*! Returns current transparency in the given result
+* \param theResult a result object
+* \return a transparency value or -1 if it was not defined
+*/
+MODELAPI_EXPORT double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult);
+
+/*! Copies all visualization attributes from one result to another.
+* \param theSource a result that contains the copied attributes
+* \param theDest a destination result that takes the visualization attributes
+*/
+MODELAPI_EXPORT void copyVisualizationAttrs(std::shared_ptr<ModelAPI_Result> theSource,
+ std::shared_ptr<ModelAPI_Result> theDest);
+
}
#endif
#include "ModelAPI.h"
#include "ModelAPI_Entity.h"
+ #include "ModelAPI_Events.h"
#include "ModelAPI_Document.h"
#include "ModelAPI_Session.h"
#include "ModelAPI_Object.h"
double aValues[3] = {anAttr->x(), anAttr->y(), anAttr->z()};
dumpArray(aResult, aValues, 3);
} else if (aType == GeomDataAPI_Dir::typeId()) {
+ if (theAttr->id() == "DistanceDirection")
+ return "__notcase__";
AttributeDirPtr anAttr = std::dynamic_pointer_cast<GeomDataAPI_Dir>(theAttr);
double aValues[3] = {anAttr->x(), anAttr->y(), anAttr->z()};
dumpArray(aResult, aValues, 3);
ModuleBase_ListView.h
ModuleBase_ModelWidget.h
ModuleBase_Operation.h
- ModuleBase_OperationAction.h
ModuleBase_OperationDescription.h
ModuleBase_OperationFeature.h
ModuleBase_PageBase.h
ModuleBase_WidgetSelectionFilter.h
ModuleBase_IStepPrs.h
ModuleBase_SelectionFilterType.h
+ ModuleBase_WidgetUndoLabel.h
)
SET(PROJECT_MOC_HEADERS
ModuleBase_ModelDialogWidget.h
ModuleBase_ModelWidget.h
ModuleBase_Operation.h
- ModuleBase_OperationAction.h
ModuleBase_OperationFeature.h
ModuleBase_PagedContainer.h
ModuleBase_PageGroupBox.h
ModuleBase_WidgetRadiobox.h
ModuleBase_WidgetPointInput.h
ModuleBase_WidgetSelectionFilter.h
+ ModuleBase_WidgetUndoLabel.h
)
SET(PROJECT_SOURCES
ModuleBase_ListView.cpp
ModuleBase_ModelWidget.cpp
ModuleBase_Operation.cpp
- ModuleBase_OperationAction.cpp
ModuleBase_OperationDescription.cpp
ModuleBase_OperationFeature.cpp
ModuleBase_PageBase.cpp
ModuleBase_WidgetPointInput.cpp
ModuleBase_WidgetSelectionFilter.cpp
ModuleBase_IStepPrs.cpp
+ ModuleBase_WidgetUndoLabel.cpp
)
SET(TEXT_RESOURCES
-# ModuleBase_msg_fr.ts
+ ModuleBase_msg_fr.ts
)
SET(PROJECT_LIBRARIES
QT5_CREATE_TRANSLATION(QM_RESOURCES
${PROJECT_FILES}
${TEXT_RESOURCES}
- OPTIONS -extensions cpp -no-recursive
+ OPTIONS -extensions cpp -no-recursive -locations none
)
ELSE(${UPDATE_TRANSLATION})
- QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ IF(${MAKE_TRANSLATION})
+ QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ ENDIF(${MAKE_TRANSLATION})
ENDIF(${UPDATE_TRANSLATION})
SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${PROJECT_COMPILED_RESOURCES} ${QM_RESOURCES})
#include <QRadioButton>
#include <QToolButton>
+const QString AStyle = "QToolButton:checked {border: 1px solid black; background-color:#C0DCF3}";
+
+
ModuleBase_ChoiceCtrl::ModuleBase_ChoiceCtrl(QWidget* theParent,
const QStringList& theChoiceList,
const QStringList& theIconsList,
QPixmap aIcon = ModuleBase_IconFactory::loadPixmap(theIconsList.at(aId));
aBtn->setIcon(aIcon);
aBtn->setIconSize(aIcon.size());
+ aBtn->setStyleSheet(AStyle);
aBtnLayout->addWidget(aBtn);
myButtons->addButton(aBtn, aId++);
}
}
-Handle(AIS_InteractiveObject) ModuleBase_IModule::createPresentation(const ObjectPtr& theResult)
+AISObjectPtr ModuleBase_IModule::createPresentation(const ObjectPtr& theResult)
{
- return Handle(AIS_InteractiveObject)();
+ return AISObjectPtr();
}
bool ModuleBase_IModule::canBeShaded(Handle(AIS_InteractiveObject) theAIS) const
return new ModuleBase_OperationFeature(theFeatureId.c_str(), this);
}
-bool ModuleBase_IModule::customizeObject(ObjectPtr theObject,
- const ModuleBase_IModule::ModuleBase_CustomizeFlag& theFlag,
- const bool theUpdateViewer)
-{
- return false;
-}
-
ModuleBase_Operation* ModuleBase_IModule::createOperation(const std::string& theFeatureId)
{
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
/// Have an opportunity to create widgets for the current operation
/// instead of standard creation in workshop
- /// \param theOperation a started operation
+ /// \param theFeature a feature of the started operation
+ /// \param theXmlRepr an XML representation of the operation
/// \param theWidgets a list of created widgets
/// \return boolean result, false by default
- virtual bool createWidgets(ModuleBase_Operation* theOperation,
+ virtual bool createWidgets(const FeaturePtr& theFeature, const QString& theXmlRepr,
QList<ModuleBase_ModelWidget*>& theWidgets) const { return false; }
//! Returns True if there are available Undos and there is not an active operation
const bool theUpdateViewer) {}
/// Modifies the given presentation in the custom way.
- virtual bool customisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
- AISObjectPtr thePrs,
- GeomCustomPrsPtr theCustomPrs) { return false; };
+ //virtual bool customisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+ // AISObjectPtr thePrs,
+ // GeomCustomPrsPtr theCustomPrs) { return false; };
- /// Modifies the given presentation in the custom way after usual customize is performed.
- virtual bool afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
- AISObjectPtr thePrs,
- GeomCustomPrsPtr theCustomPrs) { return false; };
+ ///// Modifies the given presentation in the custom way after usual customize is performed.
+ //virtual bool afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+ // AISObjectPtr thePrs,
+ // GeomCustomPrsPtr theCustomPrs) { return false; };
/// Update the object presentable properties such as color, lines width and other
/// If the object is result with the color attribute value set, it is used,
/// should be updated(e.g. only highlighted elements)
/// \param theUpdateViewer the parameter whether the viewer should be update immediately
/// \returns true if the object is modified
- virtual bool customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
- const bool theUpdateViewer);
+ virtual bool customizeFeature(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
+ const bool theUpdateViewer) {
+ return false;
+ }
/// Disable displaying of custom mode
/// \param theMode a mode to disable
/// \param theCmdId the operation name
virtual ModuleBase_Operation* createOperation(const std::string& theCmdId);
- /// Create specific for the module presentation
+ /// Create specific for the module presentation. The presentation has to be
+ /// customized accordingly to the object.
/// \param theResult an object for presentation
/// \return created presentation or NULL(default value)
- virtual Handle(AIS_InteractiveObject) createPresentation(const ObjectPtr& theResult);
+ virtual AISObjectPtr createPresentation(const ObjectPtr& theResult);
+
+ /// Customize presentation according to objects attributes
+ /// \param theObject an object for presentation
+ /// \param thePrs a presentation object
+ virtual void customizePresentation(const ObjectPtr& theObject, const AISObjectPtr& thePrs) const
+ {}
//! Returns data object by AIS
virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const = 0;
}
return aFirstWidget;
}
+
+bool ModuleBase_IPropertyPanel::isModified() const
+{
+ bool isModified = false;
+ QList<ModuleBase_ModelWidget*> aWidgets = modelWidgets();
+ foreach(ModuleBase_ModelWidget* aWgt, aWidgets) {
+ bool aRes = aWgt->isModified();
+ isModified |= aRes;
+ }
+ return isModified;
+}
/// The method is called on accepting of operation
virtual void onAcceptData() = 0;
+ /// Returns True if data of its feature was modified during operation
+ virtual bool isModified() const;
+
/// Returns the first widget, where canAcceptFocus returns true
/// \return a widget or null
static ModuleBase_ModelWidget* findFirstAcceptingValueWidget(
//! \param theAIS the object which has to be activated
virtual void applyCurrentSelectionModes(const AISObjectPtr& theAIS) = 0;
+ //! Undo last command
+ virtual void undo() = 0;
+
+ //! Set enabled state of cancel button in property panel
+ virtual void setCancelEnabled(bool toEnable) = 0;
+
+ //! Returns current state of cancel button
+ virtual bool isCancelEnabled() const = 0;
+
signals:
/// Signal selection changed.
void selectionChanged();
}
}
+//********************************************************************
+void ModuleBase_ListView::selectIndices(const std::set<int>& theIndices)
+{
+ myListControl->clearSelection();
+ for (int i = 0; i < myListControl->count(); i++) {
+ QListWidgetItem* anItem = myListControl->item(i);
+ int aId = anItem->data(ATTRIBUTE_SELECTION_INDEX_ROLE).toInt();
+ if (theIndices.find(aId) != theIndices.end()) {
+ anItem->setSelected(true);
+ }
+ }
+}
+
//********************************************************************
void ModuleBase_ListView::removeSelectedItems()
{
/// \param theIndices an output container for indices
void getSelectedIndices(std::set<int>& theIndices);
+ /// Selects items with indices
+ /// \param theIndices indices
+ void selectIndices(const std::set<int>& theIndices);
+
/// Removes selected items from the list widget
void removeSelectedItems();
//**************************************************************
ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
- const Config_WidgetAPI* theData)
- : QWidget(theParent),
- myIsEditing(false),
- myState(Stored),
- myIsValueStateBlocked(false),
- myFlushUpdateBlocked(false),
- myWidgetValidator(0)
+ const Config_WidgetAPI* theData)
+ : QWidget(theParent),
+ myIsEditing(false),
+ myState(Stored),
+ myIsValueStateBlocked(false),
+ myFlushUpdateBlocked(false),
+ myWidgetValidator(0)
{
#ifdef DEBUG_WIDGET_INSTANCE
qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget");
myIsModifiedInEdit = theData->getProperty(ATTR_MODIFIED_IN_EDIT);
+ myUpdateVisualAttributes = theData->getBooleanAttribute(ATTR_VISUAL_CHANGED, false);
+
myDefaultValue = theData->getProperty(ATTR_DEFAULT);
myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
//**************************************************************
bool ModuleBase_ModelWidget::restoreValue()
{
+ if (!isEnabled()) {
+ // This code works in inspection panel
+ ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+ if (!aValidators->isCase(myFeature, attributeID()))
+ return false; // if it is not an active case for the widget
+ }
emit beforeValuesRestored();
bool isDone = restoreValueCustom();
emit afterValuesRestored();
#ifdef DEBUG_WIDGET_INSTANCE
qDebug("ModuleBase_ModelWidget::updateObject");
#endif
+ if (myFeature.get() && myUpdateVisualAttributes) {
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES);
+ ModelAPI_EventCreator::get()->sendUpdated(myFeature, anEvent);
+ }
ModuleBase_Tools::flushUpdated(theObject);
emit objectUpdated();
}
/// By default this slot does nothing
virtual void onFeatureAccepted() {}
+ /// Returns True in case if the widget contains useful information for inspection tool
+ virtual bool isInformative() const { return true; }
+
+ /// If widgets has several panels then this method has to show a page which contains information
+ /// for current feature. By default does nothing
+ virtual void showInformativePage() {}
+
+ /// Returns True if data of its attribute was modified
+ virtual bool isModified() const { return false; }
+
+ virtual void setReadOnly(bool isReadOnly) { setEnabled(!isReadOnly); }
+
+ virtual bool isReadOnly() const { return !isEnabled(); }
+
signals:
/// The signal about widget values are to be changed
void beforeValuesChanged();
bool myIsValueStateBlocked;
/// do not flush updated signal
bool myFlushUpdateBlocked;
+
+ bool myUpdateVisualAttributes;
};
#endif
#include <GeomAPI_Pnt2d.h>
#include <Events_Loop.h>
+#include <Config_WidgetAPI.h>
+#include <Config_Keywords.h>
#include <QTimer>
ModuleBase_Operation::ModuleBase_Operation(const QString& theId, QObject* theParent)
: QObject(theParent),
myIsModified(false),
- myPropertyPanel(NULL)
+ myPropertyPanel(NULL),
+ myHideFacesVisibilityState(false)
{
myDescription = new ModuleBase_OperationDescription(theId);
}
{
return myGrantedIds.contains(theId);
}
+
+bool ModuleBase_Operation::isModified() const
+{
+ if (myDescription->hasXmlRepresentation()) {
+ Config_WidgetAPI aWidgetApi(myDescription->xmlRepresentation().toStdString());
+ if (!aWidgetApi.getBooleanAttribute(ABORT_CONFIRMATION, true))
+ return false;
+ }
+ //if (myPropertyPanel)
+ // return myPropertyPanel->isModified();
+ //return false;
+ // Most of operation causes creation of a feature
+ return true;
+}
virtual bool isGranted(QString theId) const;
/// Returns True if data of its feature was modified during operation
- virtual bool isModified() const { return myIsModified; }
-
- /// Change the modified state of the operation
- void setIsModified(const bool theIsModified) { myIsModified = theIsModified; }
+ virtual bool isModified() const;
/// Returns operations Id from it's description
QString id() const;
myHelpFileName = theName;
}
+ void setHideFacesVisible(bool isVisible) { myHideFacesVisibilityState = isVisible; }
+
+ bool isHideFacesVisible() const { return myHideFacesVisibilityState; }
+
signals:
/// The operation is started
void beforeStarted();
ModuleBase_IPropertyPanel* myPropertyPanel;
QString myHelpFileName;
+
+ /// Visibility state of HideFaces panel before the operation launch
+ bool myHideFacesVisibilityState;
};
#endif
+++ /dev/null
-// Copyright (C) 2014-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 "ModuleBase_OperationAction.h"
-
-ModuleBase_OperationAction::ModuleBase_OperationAction(const QString& theId, QObject* theParent)
- : ModuleBase_Operation(theId, theParent)
-{
-}
-
-ModuleBase_OperationAction::~ModuleBase_OperationAction()
-{
-}
-
-bool ModuleBase_OperationAction::commit()
-{
- // the action is supposed to perform a single modification,
- // so the operation returns modified state
- setIsModified(true);
-
- return ModuleBase_Operation::commit();
-}
+++ /dev/null
-// Copyright (C) 2014-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 ModuleBase_OperationAction_H
-#define ModuleBase_OperationAction_H
-
-#include <ModuleBase.h>
-
-#include <ModuleBase_Operation.h>
-
-/*!
- * \class ModuleBase_OperationAction
- * \ingroup GUI
- * \brief Base class for action operations
- *
- * This is an action-like operation, which modifies the structure of data through
- * starting/comitting transactions in the document. This operations are single stepped,
- * and have no filled property panel, like Delete/Detach.
- */
-
-class MODULEBASE_EXPORT ModuleBase_OperationAction : public ModuleBase_Operation
-{
-Q_OBJECT
-
- public:
- /// Constructor
- /// \param theId the operation identifier
- /// \param theParent the QObject parent
- ModuleBase_OperationAction(const QString& theId = "", QObject* theParent = 0);
- /// Destructor
- virtual ~ModuleBase_OperationAction();
-
- public slots:
- /// Commits the operation. Change is modified state to true value.
- /// \return the result of commit
- virtual bool commit();
-};
-
-#endif
std::shared_ptr<ModelAPI_Document> aDoc = ModelAPI_Session::get()->activeDocument();
myFeature = aDoc->addFeature(getDescription()->operationId().toStdString());
}
- if (myFeature) { // TODO: generate an error if feature was not created
- setIsModified(true);
- // Model update should call "execute" of a feature.
- //myFeature->execute();
- // Init default values
- /*QList<ModuleBase_ModelWidget*> aWidgets = getDescription()->modelWidgets();
- QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
- for (; anIt != aLast; anIt++) {
- (*anIt)->storeValue(aFeature);
- }*/
- }
-
- //if (theFlushMessage) {
- // Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
- // Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
- //}
return myFeature;
}
#ifdef DEBUG_OPERATION_START
qDebug("ModuleBase_OperationFeature::start -- begin");
#endif
- setIsModified(false);
QString anId = getDescription()->operationId();
if (myIsEditing) {
anId = anId.append(EditSuffix());
//********************************************************************
-bool ModuleBase_ResultPrs::setSubShapeHidden(const NCollection_List<TopoDS_Shape>& theShapes)
+void ModuleBase_ResultPrs::setSubShapeHidden(const TopoDS_ListOfShape& theShapes)
{
bool isModified = false;
BRep_Builder aBBuilder;
aBBuilder.MakeCompound (aCompound);
- TopoDS_Compound aShownComp;
- if (myIsSubstituted)
- aShownComp = TopoDS::Compound(Shape());
+ myHiddenSubShapes = theShapes;
+ collectSubShapes(aBBuilder, aCompound, myOriginalShape, myHiddenSubShapes);
+ myVisibleCompound = aCompound;
- // restore hidden shapes if there are not the shapes in parameter container
- NCollection_List<TopoDS_Shape> aVisibleSubShapes;
- NCollection_List<TopoDS_Shape>::Iterator aHiddenIt(myHiddenSubShapes);
- for (; aHiddenIt.More(); aHiddenIt.Next()) {
- if (!theShapes.Contains(aHiddenIt.Value())) {
- aVisibleSubShapes.Append(aHiddenIt.Value());
- }
- else {
- aBBuilder.Add(aCompound, aHiddenIt.Value());
- if (!aShownComp.IsNull())
- aBBuilder.Remove(aShownComp, aHiddenIt.Value());
- }
- }
- isModified = !aVisibleSubShapes.IsEmpty();
- NCollection_List<TopoDS_Shape>::Iterator aVisibleIt(aVisibleSubShapes);
- for (; aVisibleIt.More(); aVisibleIt.Next()) {
- if (myHiddenSubShapes.Contains(aVisibleIt.Value())) {
- myHiddenSubShapes.Remove(aVisibleIt.Value());
- if (!aShownComp.IsNull())
- aBBuilder.Add(aShownComp, aVisibleIt.Value());
- }
- }
- // append hidden shapes into internal container if there are not these shapes
- NCollection_List<TopoDS_Shape>::Iterator aShapeIt(theShapes);
- for (; aShapeIt.More(); aShapeIt.Next()) {
- if (aShapeIt.Value().ShapeType() != TopAbs_FACE) // only face shape can be hidden
- continue;
-
- if (!myHiddenSubShapes.Contains(aShapeIt.Value())) {
- myHiddenSubShapes.Append(aShapeIt.Value());
- aBBuilder.Add (aCompound, aShapeIt.Value());
- if (!aShownComp.IsNull())
- aBBuilder.Remove(aShownComp, aShapeIt.Value());
- isModified = true;
- }
+ aBBuilder.MakeCompound (aCompound);
+ TopoDS_ListOfShape::Iterator aIt(myHiddenSubShapes);
+ for (; aIt.More(); aIt.Next()) {
+ aBBuilder.Add(aCompound, aIt.Value());
}
myHiddenCompound = aCompound;
- return isModified;
}
//********************************************************************
return false;
// orientation of parameter shape(come from selection) may be wrong, check isEqual() to be sure
- for (NCollection_List<TopoDS_Shape>::Iterator aShapeIt(myHiddenSubShapes); aShapeIt.More();
- aShapeIt.Next())
- {
+ TopoDS_ListOfShape::Iterator aShapeIt(myHiddenSubShapes);
+ for (; aShapeIt.More(); aShapeIt.Next()) {
if (theShape.IsSame(aShapeIt.Value()))
return true;
}
//********************************************************************
bool ModuleBase_ResultPrs::hasSubShapeVisible(
- const NCollection_List<TopoDS_Shape>& theShapesToSkip)
+ const TopoDS_ListOfShape& theShapesToSkip)
{
TopoDS_Compound aCompound;
BRep_Builder aBuilder;
aBuilder.MakeCompound (aCompound);
- NCollection_List<TopoDS_Shape> aShapesToSkip;
- aShapesToSkip.Append(myHiddenSubShapes);
- for (NCollection_List<TopoDS_Shape>::Iterator anIt(theShapesToSkip); anIt.More(); anIt.Next())
+ TopoDS_ListOfShape aShapesToSkip;
+ TopoDS_ListOfShape aHiddenCopy(myHiddenSubShapes);
+ aShapesToSkip.Append(aHiddenCopy);
+ for (TopoDS_ListOfShape::Iterator anIt(theShapesToSkip); anIt.More(); anIt.Next())
aShapesToSkip.Append(anIt.Value());
collectSubShapes(aBuilder, aCompound, myOriginalShape, aShapesToSkip);
}
}
else { // convert shape into SHELL
- TopoDS_Compound aCompound;
- if (!myIsSubstituted) {
- BRep_Builder aBuilder;
- aBuilder.MakeCompound(aCompound);
- collectSubShapes(aBuilder, aCompound, myOriginalShape, myHiddenSubShapes);
- }
- else {
- aCompound = TopoDS::Compound(Shape());
- }
- bool isEmptyShape = BOPTools_AlgoTools3D::IsEmptyShape(aCompound);
- Set(aCompound);
+ bool isEmptyShape = BOPTools_AlgoTools3D::IsEmptyShape(myVisibleCompound);
+ Set(myVisibleCompound);
myIsSubstituted = true;
if (isEmptyShape)
aReadyToDisplay = false;
//********************************************************************
void ModuleBase_ResultPrs::collectSubShapes(BRep_Builder& theBuilder,
TopoDS_Shape& theCompound, const TopoDS_Shape& theShape,
- const NCollection_List<TopoDS_Shape>& theHiddenSubShapes)
+ const TopoDS_ListOfShape& theHiddenSubShapes)
{
switch (theShape.ShapeType()) {
case TopAbs_COMPSOLID:
/// Visual state of the face is controlled by the second parameter
/// \param theShapes a container of shape objects
/// \returns true if the presentation is changed, or false (if for example it was hidden)
- Standard_EXPORT bool setSubShapeHidden(const NCollection_List<TopoDS_Shape>& theShapes);
+ Standard_EXPORT void setSubShapeHidden(const TopoDS_ListOfShape& theShapes);
/// Returns true if parameter shape has been hidden
/// \param theShape sub-shape of the presentation shape
/// \return boolean value
Standard_EXPORT bool isSubShapeHidden(const TopoDS_Shape& theShape);
+ /// Returns hidden sub shapes list
+ Standard_EXPORT const TopoDS_ListOfShape& hiddenSubShapes() const
+ { return myHiddenSubShapes; }
+
/// Returns true if there are no hidden sub shapes or original shape has at least one not hidden
/// \param theShapesToSkip container of shape to be hidden in the presentation (faces)
/// \return boolean value
- Standard_EXPORT bool hasSubShapeVisible(const NCollection_List<TopoDS_Shape>& theShapesToSkip);
+ Standard_EXPORT bool hasSubShapeVisible(const TopoDS_ListOfShape& theShapesToSkip);
/// Set transparency of hidden sub shapes: if value is 1, shapes are entirely hidden
/// \param theTransparency transparency value
/// \param theShape the processed shape
/// \param theHiddenSubShapes container of shapes to be skipped (faces)
void collectSubShapes(BRep_Builder& theBuilder, TopoDS_Shape& theCompound,
- const TopoDS_Shape& theShape, const NCollection_List<TopoDS_Shape>& theHiddenSubShapes);
+ const TopoDS_Shape& theShape, const TopoDS_ListOfShape& theHiddenSubShapes);
void setEdgesDefaultColor();
bool myIsSubstituted;
/// Container of original Shape sub shape to be hidden and not selectable
- NCollection_List<TopoDS_Shape> myHiddenSubShapes;
+ TopoDS_ListOfShape myHiddenSubShapes;
+ TopoDS_Compound myVisibleCompound; /// compound of hidden sub shapes
TopoDS_Compound myHiddenCompound; /// compound of hidden sub shapes
double myTransparency; ///< transparency of hidden shapes, where 0 - there is no transparency
Handle(AIS_ColoredDrawer) myHiddenSubShapesDrawer; ///< drawer for hidden sub shapes
#include <ModuleBase_PagedContainer.h>
+const QString AStyle = "QToolButton:checked {border: 1px solid black; background-color:#C0DCF3}";
+
+
ModuleBase_ToolBox::ModuleBase_ToolBox(QWidget* theParent, const bool theUseFrameStyleBox)
: QFrame(theParent)
{
QToolButton* aButton = new QToolButton(myButtonsFrame);
aButton->setFocusPolicy(Qt::StrongFocus);
aButton->setCheckable(true);
+ aButton->setStyleSheet(AStyle);
if (theIcon.isNull())
aButton->setText(theName);
else {
void setSpinValue(ModuleBase_ParamSpinBox* theSpin, double theValue)
{
- if (fabs(theSpin->value() - theValue) < tolerance)
+ if (!theSpin->text().isEmpty() && fabs(theSpin->value() - theValue) < tolerance)
return;
bool isBlocked = theSpin->blockSignals(true);
theSpin->setValue(theValue);
// (for the sketch result) to start processing of the sketch in the solver.
// TODO: these flushes should be moved in a separate method provided by Model
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
std::string aTextRepr = aRef->text();
if (!aTextRepr.empty()) {
QString aText = QString::fromStdString(aTextRepr);
- //if (aText.endsWith('=')) {
- // if (!myParameter.get()) {
- // QString aName = aText.left(aText.indexOf('=')).trimmed();
- // myParameter = ModuleBase_Tools::findParameter(aName);
- // }
- // /// If myParameter is empty then it was not created because of an error
- // if (!myParameter.get())
- // return false;
-
- // AttributeStringPtr aExprAttr = myParameter->string("expression");
- // aText += aExprAttr->value().c_str();
- //}
ModuleBase_Tools::setSpinText(mySpinBox, aText);
}
else {
}
return isModified;
}
+
+bool ModuleBase_WidgetDoubleValue::isModified() const
+{
+ QString aText = mySpinBox->text();
+ if (aText.isEmpty())
+ return false;
+
+ if (myHasDefault) {
+ bool aOk = false;
+ double aVal = aText.toDouble(&aOk);
+ if (!aOk || aVal == myDefaultVal)
+ return false;
+ }
+ return true;
+}
\ No newline at end of file
/// \return a control list
virtual QList<QWidget*> getControls() const;
+ /// Returns True if data of its feature was modified during operation
+ virtual bool isModified() const;
+
public slots:
// Delayed value chnged: when user starts typing something,
// it gives him a 0,5 second to finish typing, when sends valueChnaged() signal
#include <ModuleBase_WidgetMultiSelector.h>
#include <ModuleBase_WidgetConcealedObjects.h>
#include <ModuleBase_WidgetLabel.h>
+#include <ModuleBase_WidgetUndoLabel.h>
#include <ModuleBase_WidgetToolbox.h>
#include <ModuleBase_WidgetRadiobox.h>
#include <ModuleBase_PageBase.h>
result = new ModuleBase_WidgetLabel(theParent, myWidgetApi);
} else if (theType == WDG_DOUBLEVALUE) {
result = new ModuleBase_WidgetDoubleValue(theParent, myWidgetApi);
+ } else if (theType == WDG_UNDOLABEL) {
+ result = new ModuleBase_WidgetUndoLabel(theParent, myWorkshop, myWidgetApi);
} else if (theType == WDG_DOUBLEVALUELABEL) {
result = new ModuleBase_WidgetLabelValue(theParent, myWidgetApi);
} else if (theType == WDG_INTEGERVALUE) {
}
return isModified;
}
+
+bool ModuleBase_WidgetIntValue::isModified() const
+{
+ QString aText = mySpinBox->text();
+ if (aText.isEmpty())
+ return false;
+
+ if (myHasDefault) {
+ bool aOk = false;
+ int aVal = aText.toInt(&aOk);
+ if (!aOk || aVal == myDefVal)
+ return false;
+ }
+ return true;
+}
\ No newline at end of file
/// \return a control list
virtual QList<QWidget*> getControls() const;
+ /// Returns True if data of its feature was modified during operation
+ virtual bool isModified() const;
+
protected:
/// Returns true if the event is processed.
virtual bool processEnter();
: ModuleBase_ModelWidget(theParent, theData)
{
QString aText = translate(theData->getProperty("title"));
+ bool aIsHtml = theData->getBooleanAttribute(ATTR_HTML_STYLE, false);
+
QString aLabelIcon = QString::fromStdString(theData->getProperty("icon"));
myLabel = new QLabel(aText, theParent);
if (!aLabelIcon.isEmpty()) {
myLabel->setWordWrap(true);
myLabel->setIndent(5);
myLabel->setContentsMargins(0,0,0,4);
+ if (aIsHtml)
+ myLabel->setTextFormat(Qt::RichText);
QVBoxLayout* aLayout = new QVBoxLayout(this);
ModuleBase_Tools::zeroMargins(aLayout);
aLayout->addWidget(myLabel);
setLayout(aLayout);
- std::string aStyleSheet = theData->getProperty(ATTR_STYLE_SHEET).c_str();
+ std::string aStyleSheet = theData->getProperty(ATTR_STYLE_SHEET);
if (!aStyleSheet.empty())
myLabel->setStyleSheet(QString("QLabel {%1}").arg(aStyleSheet.c_str()));
}
}
return isModified;
}
+
+bool ModuleBase_WidgetLineEdit::isModified() const
+{
+ return !myLineEdit->text().isEmpty();
+}
\ No newline at end of file
/// Redefinition of virtual method
virtual QList<QWidget*> getControls() const;
+ /// Returns True if data of its feature was modified during operation
+ virtual bool isModified() const;
+
protected:
/// Returns true if the event is processed.
virtual bool processEnter();
const Config_WidgetAPI* theData)
: ModuleBase_WidgetSelector(theParent, theWorkshop, theData),
myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1),
- myIsFirst(true), myFiltersWgt(0)
+ myIsFirst(true), myFiltersWgt(0), myShowOnlyBtn(0)
{
std::string aPropertyTypes = theData->getProperty("shape_types");
QString aTypesStr = aPropertyTypes.c_str();
if (!aAllowedList.isEmpty())
myAllowedObjects = aAllowedList.split(' ', QString::SkipEmptyParts);
- QVBoxLayout* aMainLay = new QVBoxLayout(this);
- ModuleBase_Tools::adjustMargins(aMainLay);
+ myMainLayout = new QVBoxLayout(this);
+ ModuleBase_Tools::adjustMargins(myMainLayout);
QStringList aIconsList = getIconsList(myShapeTypes);
myTypeCtrl = new ModuleBase_ChoiceCtrl(this, myShapeTypes, aIconsList);
myTypeCtrl->setValue(0);
myDefMode = myShapeTypes.first().toStdString();
}
- aMainLay->addWidget(myTypeCtrl);
+ myMainLayout->addWidget(myTypeCtrl);
// There is no sense to parameterize list of types while we can not parameterize selection mode
// if the xml definition contains one type, the controls to select a type should not be shown
QWidget* aLabelWgt = new QWidget(this);
QHBoxLayout* aLabelLayout = new QHBoxLayout(aLabelWgt);
aLabelLayout->setContentsMargins(0, 0, 0, 0);
- aMainLay->addWidget(aLabelWgt);
+ myMainLayout->addWidget(aLabelWgt);
QLabel* aListLabel = new QLabel(aLabelText, this);
aLabelLayout->addWidget(aListLabel);
connect(myListView, SIGNAL(deleteActionClicked()), SLOT(onDeleteItem()));
connect(myListView, SIGNAL(listActivated()), SLOT(onListActivated()));
- aMainLay->addWidget(myListView->getControl());
+ myMainLayout->addWidget(myListView->getControl());
connect(myTypeCtrl, SIGNAL(valueChanged(int)), this, SLOT(onSelectionTypeChanged()));
- std::string aUseFilters = theData->getProperty("use_filters");
- if (aUseFilters.length() > 0) {
+ myUseFilters = theData->getProperty("use_filters");
+ if (myUseFilters.length() > 0) {
QWidget* aFltrWgt = new QWidget(this);
QHBoxLayout* aFltrLayout = new QHBoxLayout(aFltrWgt);
- myFiltersWgt = new ModuleBase_FilterStarter(aUseFilters.c_str(), aFltrWgt, theWorkshop);
+ myFiltersWgt = new ModuleBase_FilterStarter(myUseFilters, aFltrWgt, theWorkshop);
aFltrLayout->addWidget(myFiltersWgt);
aFltrLayout->addStretch();
- QPushButton* aShowBtn = new QPushButton(tr("Show only"), aFltrWgt);
- aShowBtn->setCheckable(true);
- aShowBtn->setChecked(false);
- connect(aShowBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
- aFltrLayout->addWidget(aShowBtn);
+ myShowOnlyBtn = new QPushButton(tr("Show only"), aFltrWgt);
+ myShowOnlyBtn->setCheckable(true);
+ myShowOnlyBtn->setChecked(false);
+ connect(myShowOnlyBtn, SIGNAL(toggled(bool)), SLOT(onShowOnly(bool)));
+ aFltrLayout->addWidget(myShowOnlyBtn);
- aMainLay->addWidget(aFltrWgt);
+ myMainLayout->addWidget(aFltrWgt);
}
bool aSameTop = theData->getBooleanAttribute("same_topology", false);
if (aSameTop) {
myGeomCheck = new QCheckBox(tr("Add elements that share the same topology"), this);
- aMainLay->addWidget(myGeomCheck);
+ myMainLayout->addWidget(myGeomCheck);
connect(myGeomCheck, SIGNAL(toggled(bool)), SLOT(onSameTopology(bool)));
}
else
theValues.append(anInvalidValues);
if (isDone) // may be the feature's result is not displayed, but attributes should be
- myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
+ myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeArguments,
true);/// hope that something is redisplayed by object updated
return isDone;
myWorkshop->setSelected(getAttributeSelection());
// may be the feature's result is not displayed, but attributes should be
- myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
+ myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeArguments,
true); /// hope that something is redisplayed by object updated
}
restoreValue();
myWorkshop->setSelected(getAttributeSelection());
// may be the feature's result is not displayed, but attributes should be
- myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments,
+ myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeArguments,
true); /// hope that something is redisplayed by object updated
// clear history should follow after set selected to do not increase history by setSelected
clearSelectedHistory();
//********************************************************************
void ModuleBase_WidgetMultiSelector::onListSelection()
{
- myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
- true);
+ myWorkshop->module()->customizeFeature(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
+ true);
}
//********************************************************************
myVisibleObjects.clear();
} else
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ myWorkshop->viewer()->update();
+}
+
+bool ModuleBase_WidgetMultiSelector::isModified() const
+{
+ return myListView->getControl()->count() > 0;
+}
+
+
+void ModuleBase_WidgetMultiSelector::setReadOnly(bool isReadOnly)
+{
+ ModuleBase_WidgetSelector::setReadOnly(isReadOnly);
+ if (myShowOnlyBtn)
+ myShowOnlyBtn->hide();
+ if (myFiltersWgt) {
+ myFiltersWgt->hide();
+
+ AttributeSelectionListPtr aAttrList = feature()->selectionList(attributeID());
+ if (aAttrList.get()) {
+ FiltersFeaturePtr aFilters = aAttrList->filters();
+ if (aFilters.get()) {
+ ModuleBase_WidgetSelectionFilter::SelectorFeature = feature();
+ ModuleBase_WidgetSelectionFilter::AttributeId = attributeID();
+
+ std::string aXmlCfg, aDescription;
+ myWorkshop->module()->getXMLRepresentation(myUseFilters, aXmlCfg, aDescription);
+
+ ModuleBase_WidgetSelectionFilter* aWgt =
+ new ModuleBase_WidgetSelectionFilter(this, myWorkshop,
+ new Config_WidgetAPI(aDescription), true);
+ aWgt->setFeature(aFilters);
+ aWgt->restoreValue();
+ myMainLayout->addWidget(aWgt);
+ }
+ }
+ }
}
class QWidget;
class QCheckBox;
-//class QComboBox;
+class QPushButton;
+class QVBoxLayout;
class ModuleBase_ListView;
class ModuleBase_IWorkshop;
class ModuleBase_ChoiceCtrl;
/// The slot is called when user press Ok or OkPlus buttons in the parent property panel
virtual void onFeatureAccepted();
+ /// Returns True if data of its feature was modified during operation
+ virtual bool isModified() const;
+
+ virtual void setReadOnly(bool isReadOnly);
+
public slots:
/// Slot is called on selection type changed
void onSelectionTypeChanged();
bool myIsFirst;
std::string myDefMode;
+ QVBoxLayout* myMainLayout;
QCheckBox* myGeomCheck;
ModuleBase_FilterStarter* myFiltersWgt;
+ QPushButton* myShowOnlyBtn;
QObjectPtrList myVisibleObjects;
QStringList myAllowedObjects;
QStringList myTmpAllowed;
+ std::string myUseFilters;
};
#endif /* MODULEBASE_WIDGETFILESELECTOR_H_ */
#include <QCheckBox>
#include <QDir>
-static FeaturePtr SelectorFeature;
-static std::string AttributeId;
+FeaturePtr ModuleBase_WidgetSelectionFilter::SelectorFeature;
+std::string ModuleBase_WidgetSelectionFilter::AttributeId;
GeomAPI_Shape::ShapeType selectionType(const QString& theType)
}
if (!aSelector)
return;
- SelectorFeature = aSelector->feature();
- AttributeId = aSelector->attributeID();
+ ModuleBase_WidgetSelectionFilter::SelectorFeature = aSelector->feature();
+ ModuleBase_WidgetSelectionFilter::AttributeId = aSelector->attributeID();
// Launch Filters operation
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
(myWorkshop->module()->createOperation(myFeatureName));
- AttributeSelectionListPtr aAttrList = SelectorFeature->selectionList(AttributeId);
+ AttributeSelectionListPtr aAttrList =
+ ModuleBase_WidgetSelectionFilter::SelectorFeature->selectionList(
+ ModuleBase_WidgetSelectionFilter::AttributeId);
FiltersFeaturePtr aFilters = aAttrList->filters();
if (aFilters.get())
aFOperation->setFeature(aFilters);
//*****************************************************************************
//*****************************************************************************
ModuleBase_WidgetSelectionFilter::ModuleBase_WidgetSelectionFilter(QWidget* theParent,
- ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData)
+ ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData, bool theReadOnly)
: ModuleBase_ModelWidget(theParent, theData),
myWorkshop(theWorkshop),
- mySelectorFeature(SelectorFeature),
- mySelectorAttribute(AttributeId)
+ mySelectorFeature(ModuleBase_WidgetSelectionFilter::SelectorFeature),
+ mySelectorAttribute(ModuleBase_WidgetSelectionFilter::AttributeId)
{
// Clear Old selection
- AttributeSelectionListPtr aAttrList = mySelectorFeature->selectionList(mySelectorAttribute);
- mySelectionType = selectionType(aAttrList->selectionType().c_str());
- aAttrList->clear();
+ AttributeSelectionListPtr aAttrList = mySelectorFeature->selectionList(mySelectorAttribute);
+ mySelectionType = selectionType(aAttrList->selectionType().c_str());
+ if (!theReadOnly) {
+ aAttrList->clear();
+ }
// Define widgets
QVBoxLayout* aMainLayout = new QVBoxLayout(this);
aMainLayout->addStretch(1);
updateSelectBtn();
+ if (theReadOnly) {
+ myFiltersCombo->hide();
+ mySelectBtn->hide();
+ aLblWgt->hide();
+ myShowBtn->hide();
+ }
}
ModuleBase_WidgetSelectionFilter::~ModuleBase_WidgetSelectionFilter()
{
ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters();
FiltersFeaturePtr aFiltersFeature = std::dynamic_pointer_cast<ModelAPI_FiltersFeature>(myFeature);
+
+ // Init filters member of the parent attribute
+ AttributeSelectionListPtr aAttrList = mySelectorFeature->selectionList(mySelectorAttribute);
+ if (aAttrList->filters() != aFiltersFeature) {
+ aAttrList->setFilters(aFiltersFeature);
+ }
+
std::list<std::string> aFilters = aFiltersFeature->filters();
std::list<std::string>::const_iterator aIt;
for (aIt = aFilters.cbegin(); aIt != aFilters.cend(); aIt++) {
std::string aStr = (*aIt);
- onAddFilter(aStr);
+ ModuleBase_FilterItem* aItem = onAddFilter(aStr);
FilterPtr aFilterObj = aFactory->filter(aStr);
int aId = myFiltersCombo->findText(aFilterObj->name().c_str());
if (aId != -1)
myFiltersCombo->removeItem(aId);
- }
- // Init filters member of the parent attribute
- AttributeSelectionListPtr aAttrList = mySelectorFeature->selectionList(mySelectorAttribute);
- if (aAttrList->filters() != aFiltersFeature) {
- aAttrList->setFilters(aFiltersFeature);
- }
- QList<QWidget*> aWidgets;
- QList<ModuleBase_FilterItem*> aItems = myFiltersLayout->findChildren<ModuleBase_FilterItem*>();
- foreach(ModuleBase_FilterItem* aItem, aItems) {
- QList<ModuleBase_ModelWidget*> aSubList = aItem->widgets();
- foreach(ModuleBase_ModelWidget* aWgt, aSubList) {
- aWgt->restoreValue();
+ if (aItem) {
+ QList<ModuleBase_ModelWidget*> aSubList = aItem->widgets();
+ foreach(ModuleBase_ModelWidget* aWgt, aSubList) {
+ aWgt->restoreValue();
+ }
}
}
return true;
{
Q_OBJECT
public:
+ static FeaturePtr SelectorFeature;
+ static std::string AttributeId;
+
/// Constructor
/// \param theParent the parent object
/// \param theData the widget configuration. The attribute of the model widget is obtained from
/// a low-level API for reading xml definitions of widgets
ModuleBase_WidgetSelectionFilter(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop,
- const Config_WidgetAPI* theData);
+ const Config_WidgetAPI* theData, bool theReadOnly = false);
/// Destructor
~ModuleBase_WidgetSelectionFilter();
}
}
}
+
+//********************************************************************
+bool ModuleBase_WidgetShapeSelector::isModified() const
+{
+ return !myTextLine->text().isEmpty();
+}
\ No newline at end of file
/// \return a control list
virtual QList<QWidget*> getControls() const;
+ /// Returns True if data of its feature was modified during operation
+ virtual bool isModified() const;
+
protected:
/// Saves the internal parameters to the given feature
/// \return True in success
--- /dev/null
+// Copyright (C) 2014-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 "ModuleBase_WidgetUndoLabel.h"
+#include "ModuleBase_IWorkshop.h"
+
+#include <QPushButton>
+#include <QLayout>
+#include <QString>
+#include <QLabel>
+
+ModuleBase_WidgetUndoLabel::ModuleBase_WidgetUndoLabel(QWidget* theParent,
+ ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData)
+ : ModuleBase_WidgetLabel(theParent, theData),
+ myWorkshop(theWorkshop)
+{
+ myUndoBtn = new QPushButton(tr("Undo"), this);
+ myUndoBtn->hide();
+ layout()->addWidget(myUndoBtn);
+ connect(myUndoBtn, SIGNAL(clicked(bool)), SLOT(onUndo()));
+}
+
+
+bool ModuleBase_WidgetUndoLabel::restoreValueCustom()
+{
+ bool aRes = ModuleBase_WidgetLabel::restoreValueCustom();
+ bool aError = myLabel->text().length() > 0;
+ myUndoBtn->setVisible(aError);
+ myWorkshop->setCancelEnabled(!aError);
+ return aRes;
+}
+
+
+void ModuleBase_WidgetUndoLabel::onUndo()
+{
+ myWorkshop->undo();
+}
\ No newline at end of file
--- /dev/null
+// Copyright (C) 2014-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 ModuleBase_WidgetUndoLabel_H
+#define ModuleBase_WidgetUndoLabel_H
+
+#include "ModuleBase.h"
+#include "ModuleBase_WidgetLabel.h"
+
+class QPushButton;
+class ModuleBase_IWorkshop;
+
+/**
+* \ingroup GUI
+* Implementation of model widget for a label control
+*/
+class MODULEBASE_EXPORT ModuleBase_WidgetUndoLabel : public ModuleBase_WidgetLabel
+{
+ Q_OBJECT
+public:
+ /// Constructor
+ /// \param theParent the parent object
+ /// \param theData the widget configuation. The attribute of the model widget is obtained from
+ ModuleBase_WidgetUndoLabel(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData);
+
+ virtual ~ModuleBase_WidgetUndoLabel() {}
+
+ virtual bool restoreValueCustom();
+
+private slots:
+ void onUndo();
+
+private:
+ ModuleBase_IWorkshop* myWorkshop;
+ QPushButton* myUndoBtn;
+};
+
+#endif
\ No newline at end of file
#include <ModelAPI_Validator.h>
#include <ModelAPI_AttributeValidator.h>
#include <ModelAPI_Events.h>
-#include <ModelAPI_ResultBody.h>
#include <ModelAPI_Tools.h>
#include <ModelAPI_AttributeSelection.h>
myAttributeStore->restoreAttributeValue(theAttribute, myWorkshop);
}
+
+//********************************************************************
+void ModuleBase_WidgetValidated::collectSubBodies(const ResultBodyPtr& theBody,
+ AIS_NListOfEntityOwner& theList)
+{
+ AISObjectPtr aIOPtr;
+ TopoDS_Shape aTDShape;
+ int aNb = theBody->numberOfSubs();
+ for (int i = 0; i < aNb; i++) {
+ ResultBodyPtr aSub = theBody->subResult(i);
+ if (aSub->numberOfSubs() > 0)
+ collectSubBodies(aSub, theList);
+ else {
+ aTDShape = aSub->shape()->impl<TopoDS_Shape>();
+ aIOPtr = myWorkshop->findPresentation(aSub);
+ if (aIOPtr.get()) {
+ Handle(AIS_InteractiveObject) anIO = aIOPtr->impl<Handle(AIS_InteractiveObject)>();
+ theList.Append(new StdSelect_BRepOwner(aTDShape, anIO));
+ }
+ else
+ theList.Append(new StdSelect_BRepOwner(aTDShape));
+ }
+ }
+}
+
//********************************************************************
bool ModuleBase_WidgetValidated::isValidInFilters(const ModuleBase_ViewerPrsPtr& thePrs)
{
Handle(AIS_InteractiveObject) anIO = myWorkshop->selection()->getIO(thePrs);
aOwnersList.Append(new StdSelect_BRepOwner(aTDShape, anIO));
}
- else
- aValid = false;
- //aSelectAttr->setValue(ObjectPtr(), GeomShapePtr(), true);
}
else {
ResultPtr aResult = aFeature->firstResult();
if (aResult.get()) {
- GeomShapePtr aShapePtr = ModelAPI_Tools::shape(aResult);
- if (aShapePtr.get()) {
- const TopoDS_Shape aTDShape = aShapePtr->impl<TopoDS_Shape>();
- AISObjectPtr aIOPtr = myWorkshop->findPresentation(aResult);
- if (aIOPtr.get()) {
- Handle(AIS_InteractiveObject) anIO = aIOPtr->impl<Handle(AIS_InteractiveObject)>();
- aOwnersList.Append(new StdSelect_BRepOwner(aTDShape, anIO));
- }
- else {
- aOwnersList.Append(new StdSelect_BRepOwner(aTDShape));
+ ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+ if (aBody.get() && (aBody->numberOfSubs() > 0))
+ collectSubBodies(aBody, aOwnersList);
+ else {
+ GeomShapePtr aShapePtr = ModelAPI_Tools::shape(aResult);
+ if (aShapePtr.get()) {
+ TopoDS_Shape aTDShape = aShapePtr->impl<TopoDS_Shape>();
+ AISObjectPtr aIOPtr = myWorkshop->findPresentation(aResult);
+ if (aIOPtr.get()) {
+ Handle(AIS_InteractiveObject) anIO =
+ aIOPtr->impl<Handle(AIS_InteractiveObject)>();
+ aOwnersList.Append(new StdSelect_BRepOwner(aTDShape, anIO));
+ }
+ else
+ aOwnersList.Append(new StdSelect_BRepOwner(aTDShape));
}
}
}
- aValid = (aOwnersList.Size() > 0); // only results with a shape can be filtered
}
- } else
- aValid = false; // only results with a shape can be filtered
+ }
}
}
+ aValid = (aOwnersList.Size() > 0); // only results with a shape can be filtered
+
// checks the owner by the AIS context activated filters
if (aOwnersList.Size() > 0) {
// the widget validator filter should be active, but during check by preselection
#include <GeomAPI_AISObject.h>
#include <ModelAPI_Object.h>
#include <ModelAPI_Attribute.h>
+#include <ModelAPI_ResultBody.h>
#include <SelectMgr_ListOfFilter.hxx>
#include <NCollection_DataMap.hxx>
#include <TopoDS_Shape.hxx>
+#include <AIS_NListOfEntityOwner.hxx>
#include <QList>
#include <QMap>
/// \param theValues a list of presentations.
void filterCompSolids(QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues);
+ void collectSubBodies(const ResultBodyPtr& theBody, AIS_NListOfEntityOwner& theList);
+
protected:
/// Reference to workshop
ModuleBase_IWorkshop* myWorkshop;
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>ExpressionEditor</name>
+ <message>
+ <source>Ctrl+Space</source>
+ <comment>Complete</comment>
+ <translation>Ctrl+Espace</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_FilterItem</name>
+ <message>
+ <source>Reverse the filter</source>
+ <translation>Inverser le filtre</translation>
+ </message>
+ <message>
+ <source>Delete the filter</source>
+ <translation>Supprimer le filtre</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_FilterStarter</name>
+ <message>
+ <source>Selection by filters</source>
+ <translation>Sélection par filtres</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_ListView</name>
+ <message>
+ <source>Copy</source>
+ <translation>Copie</translation>
+ </message>
+ <message>
+ <source>Delete</source>
+ <translation>Effacer</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_PreferencesDlg</name>
+ <message>
+ <source>Edit preferences</source>
+ <translation>Modifier les préférences</translation>
+ </message>
+ <message>
+ <source>Default</source>
+ <translation>Défaut</translation>
+ </message>
+ <message>
+ <source>Desktop</source>
+ <translation>Bureau</translation>
+ </message>
+ <message>
+ <source>Module</source>
+ <translation>Module</translation>
+ </message>
+ <message>
+ <source>Viewer</source>
+ <translation>Vue</translation>
+ </message>
+ <message>
+ <source>Horizontal gradient</source>
+ <translation>Dégradé horizontal</translation>
+ </message>
+ <message>
+ <source>Vertical gradient</source>
+ <translation>Gradient vertical</translation>
+ </message>
+ <message>
+ <source>First diagonal gradient</source>
+ <translation>Premier gradient en diagonale</translation>
+ </message>
+ <message>
+ <source>Second diagonal gradient</source>
+ <translation>Deuxième gradient diagonal</translation>
+ </message>
+ <message>
+ <source>First corner gradient</source>
+ <translation>Premier angle de dégradé</translation>
+ </message>
+ <message>
+ <source>Second corner gradient</source>
+ <translation>Deuxième angle du dégradé</translation>
+ </message>
+ <message>
+ <source>Third corner gradient</source>
+ <translation>Troisième angle de dégradé</translation>
+ </message>
+ <message>
+ <source>Fourth corner gradient</source>
+ <translation>Quatrième angle</translation>
+ </message>
+ <message>
+ <source>Background</source>
+ <translation>Arrière-plan</translation>
+ </message>
+ <message>
+ <source>Viewer 3d</source>
+ <translation>Vue 3d</translation>
+ </message>
+ <message>
+ <source>Default selection</source>
+ <translation>Sélection par défaut</translation>
+ </message>
+ <message>
+ <source>Faces</source>
+ <translation>Faces</translation>
+ </message>
+ <message>
+ <source>Edges</source>
+ <translation>Arêtes</translation>
+ </message>
+ <message>
+ <source>Vertices</source>
+ <translation>Sommets</translation>
+ </message>
+ <message>
+ <source>Selection sensitivity</source>
+ <translation>Sensibilité de sélection</translation>
+ </message>
+ <message>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <source>Additional highlighting</source>
+ <translation>Mise en évidence supplémentaire</translation>
+ </message>
+ <message>
+ <source>In 3d mode</source>
+ <translation>En mode 3D</translation>
+ </message>
+ <message>
+ <source>In 2d mode</source>
+ <translation>En mode 2D</translation>
+ </message>
+ <message>
+ <source>Color scale</source>
+ <translation>Échelle de couleur</translation>
+ </message>
+ <message>
+ <source>X position</source>
+ <translation>Position X</translation>
+ </message>
+ <message>
+ <source>Y position</source>
+ <translation>Position Y</translation>
+ </message>
+ <message>
+ <source>Width</source>
+ <translation>Largeur</translation>
+ </message>
+ <message>
+ <source>Height</source>
+ <translation>Hauteur</translation>
+ </message>
+ <message>
+ <source>Intervals number</source>
+ <translation>Nombre d'intervalles</translation>
+ </message>
+ <message>
+ <source>Text height</source>
+ <translation>Hauteur du texte</translation>
+ </message>
+ <message>
+ <source>Text color</source>
+ <translation>Couleur du texte</translation>
+ </message>
+ <message>
+ <source>Main menu</source>
+ <translation>Menu principal</translation>
+ </message>
+ <message>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ <message>
+ <source>Number of rows</source>
+ <translation>Nombre de rangées</translation>
+ </message>
+ <message>
+ <source>Show Status Bar</source>
+ <translation>Afficher la barre d'état</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_WidgetFileSelector</name>
+ <message>
+ <source>Select file...</source>
+ <translation>Choisir le dossier...</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_WidgetMultiSelector</name>
+ <message>
+ <source>Type</source>
+ <translation>Type</translation>
+ </message>
+ <message>
+ <source>Show only</source>
+ <translation>Montrer seulement</translation>
+ </message>
+ <message>
+ <source>Add elements that share the same topology</source>
+ <translation>Ajouter des éléments qui partagent la même topologie</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_WidgetPointInput</name>
+ <message>
+ <source>X coordinate</source>
+ <translation>Coordonnée X</translation>
+ </message>
+ <message>
+ <source>Y coordinate</source>
+ <translation>Coordonnée Y</translation>
+ </message>
+ <message>
+ <source>Z coordinate</source>
+ <translation>Coordonnée Z</translation>
+ </message>
+</context>
+<context>
+ <name>ModuleBase_WidgetSelectionFilter</name>
+ <message>
+ <source>Filters</source>
+ <translation>Filtres</translation>
+ </message>
+ <message>
+ <source>Add new filter...</source>
+ <translation>Ajouter un nouveau filtre...</translation>
+ </message>
+ <message>
+ <source>Select</source>
+ <translation>Sélectionner</translation>
+ </message>
+ <message>
+ <source>Number of selected objects:</source>
+ <translation>Nombre d'objets sélectionnés:</translation>
+ </message>
+ <message>
+ <source>Show only</source>
+ <translation>Montrer seulement</translation>
+ </message>
+ <message>
+ <source>Selection is empty</source>
+ <translation>La sélection est vide</translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Selected objects can be used in Part documents which are not loaded: %1.
+</source>
+ <translation>Les objets sélectionnés peuvent être utilisés dans les documents de pièce non chargés : %1.
+</translation>
+ </message>
+ <message>
+ <source>Delete features</source>
+ <translation>Supprimer les fonctionnalités</translation>
+ </message>
+ <message>
+ <source>The following parts will be deleted: %1.
+</source>
+ <translation>Les pièces suivantes seront supprimées : %1.
+
+</translation>
+ </message>
+ <message>
+ <source>Replace</source>
+ <translation>Remplacer</translation>
+ </message>
+</context>
+</TS>
SET(TEXT_RESOURCES
ParametersPlugin_msg_ru.ts
ParametersPlugin_msg_en.ts
+ ParametersPlugin_msg_fr.ts
)
# QT4_CREATE_TRANSLATION(QM_RESOURCES
#include <ModuleBase_Tools.h>
#include <Events_Loop.h>
+#include <Config_PropManager.h>
#include <QLayout>
#include <QPushButton>
#include <QEvent>
#include <QKeyEvent>
#include <QDialogButtonBox>
+#include <QShortcut>
enum ColumnType {
Col_Name,
connect(myAddBtn, SIGNAL(clicked(bool)), SLOT(onAdd()));
aBtnLayout->addWidget(myAddBtn);
+ QString aAddStr(Config_PropManager::string("Shortcuts", "add_parameter_shortcut").c_str());
+ if (aAddStr.isEmpty())
+ aAddStr = "Ctrl+A";
+
+ QShortcut* aAddShc = new QShortcut(QKeySequence(aAddStr), myAddBtn);
+ connect(aAddShc, SIGNAL(activated()), SLOT(onAdd()));
+
myInsertBtn = new QPushButton(translate("Insert"), this);
connect(myInsertBtn, SIGNAL(clicked(bool)), SLOT(onInsert()));
aBtnLayout->addWidget(myInsertBtn);
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Parameter</source>
+ <translation>Paramètre</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>ModuleBase_Dialog</name>
+ <message>
+ <source>Parameters</source>
+ <translation>Paramètres</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Parameter</name>
+ <message>
+ <source>Create a parameter</source>
+ <translation>Créer un paramètre</translation>
+ </message>
+ <message>
+ <source>Parameter</source>
+ <translation>Paramètre</translation>
+ </message>
+ <message>
+ <source>Attribute "variable" is not initialized.</source>
+ <translation>Définir le nom de la variable</translation>
+ </message>
+ <message>
+ <source>Expression error.</source>
+ <translation>Erreur d'expression.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Parameter:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "expression" is not initialized.</source>
+ <translation>Définir l'expression</translation>
+ </message>
+ </context>
+ <context>
+ <name>Parameter:comment</name>
+ <message>
+ <source>Comment</source>
+ <translation>Commentaire</translation>
+ </message>
+ </context>
+ <context>
+ <name>Parameter:expression</name>
+ <message>
+ <source>Please input the expression</source>
+ <translation>S'il vous plaît entrer l'expression</translation>
+ </message>
+ </context>
+ <context>
+ <name>Parameter:expression:Parameters_ExpressionValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Parameter:variable</name>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Please input the parameter name</source>
+ <translation>Veuillez saisir le nom du paramètre</translation>
+ </message>
+ </context>
+ <context>
+ <name>Parameter:variable:Parameters_VariableValidator</name>
+ <message>
+ <source>Attribute "%1" value is empty.</source>
+ <translation>La valeur de l'attribut "%1" est vide.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>ParametersMgr</name>
+ <message>
+ <source>Manage parameters</source>
+ <translation>Gérer les paramètres</translation>
+ </message>
+ <message>
+ <source>Parameters</source>
+ <translation>Paramètres</translation>
+ </message>
+ </context>
+ <context>
+ <name>ParametersMgr</name>
+ <message>
+ <source>Add</source>
+ <translation>Ajouter</translation>
+ </message>
+ <message>
+ <source>Comment</source>
+ <translation>Commentaire</translation>
+ </message>
+ <message>
+ <source>Expression</source>
+ <translation>Expression</translation>
+ </message>
+ <message>
+ <source>Features</source>
+ <translation>Caractéristiques</translation>
+ </message>
+ <message>
+ <source>Insert</source>
+ <translation>Insérer</translation>
+ </message>
+ <message>
+ <source>Name</source>
+ <translation>Nom</translation>
+ </message>
+ <message>
+ <source>Remove</source>
+ <translation>Retirer</translation>
+ </message>
+ <message>
+ <source>Result</source>
+ <translation>Résultat</translation>
+ </message>
+ <message>
+ <source>See preview</source>
+ <translation>Voir l'aperçu</translation>
+ </message>
+ <message>
+ <source><NoName></source>
+ <translation><SansNom></translation>
+ </message>
+ <message>
+ <source><NoValue></source>
+ <translation><AucuneValeur></translation>
+ </message>
+ </context>
+
+ <context>
+ <name>ParametersPlugin</name>
+ <message>
+ <source>Warning</source>
+ <translation>Attention</translation>
+ </message>
+ <message>
+ <source>Selected objects can be used in Part documents which are not loaded: %1. Would you like to continue?</source>
+ <translation>Les objets sélectionnés peuvent être utilisés dans les documents de pièce non chargés : %1. Voulez-vous continuer ?</translation>
+ </message>
+ </context>
+
+</TS>
)
SET(TEXT_RESOURCES
-# PartSet_msg_fr.ts
+ PartSet_msg_fr.ts
)
SET(PROJECT_LIBRARIES
QT_ADD_RESOURCES(PROJECT_COMPILED_RESOURCES ${PROJECT_RESOURCES})
IF (${UPDATE_TRANSLATION})
- SET(PROJECT_FILES ${PROJECT_SOURCES} ${ROJECT_HEADERS} )
+ SET(PROJECT_FILES ${PROJECT_SOURCES} ${PROJECT_HEADERS} )
QT5_CREATE_TRANSLATION(QM_RESOURCES
${PROJECT_FILES}
${TEXT_RESOURCES}
- OPTIONS -extensions cpp -no-recursive
+ OPTIONS -extensions cpp -no-recursive -locations none
)
ELSE(${UPDATE_TRANSLATION})
- QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ IF(${MAKE_TRANSLATION})
+ QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ ENDIF(${MAKE_TRANSLATION})
ENDIF(${UPDATE_TRANSLATION})
SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${PROJECT_COMPILED_RESOURCES} ${QM_RESOURCES})
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-#include <PartSet_CustomPrs.h>
-#include <PartSet_Module.h>
+#include "PartSet_CustomPrs.h"
+#include "PartSet_Module.h"
#include "PartSet_OperationPrs.h"
#include "PartSet_OverconstraintListener.h"
+#include "PartSet_SketcherMgr.h"
#include <XGUI_ModuleConnector.h>
#include <XGUI_Workshop.h>
#include <ModuleBase_IViewer.h>
#include <ModuleBase_Tools.h>
+#include <ModelAPI_Tools.h>
+#include <SketchPlugin_Sketch.h>
+
#include <Config_PropManager.h>
#include <Events_Loop.h>
#include <ModelAPI_Events.h>
#ifdef DO_NOT_VISUALIZE_CUSTOM_PRESENTATION
return false;
#endif
+ bool isModified = false;
- myIsActive[theFlag] = true;
- myFeature = theFeature;
+ // Do not call customisation for sketcher and all its sub-objects
+ if (theFeature->getKind() == SketchPlugin_Sketch::ID())
+ return isModified;
+
+ FeaturePtr aParent = ModelAPI_Tools::compositeOwner(theFeature);
+ if (aParent.get()) {
+ std::string aType = aParent->getKind();
+ if (aType == SketchPlugin_Sketch::ID())
+ return isModified;
+ }
- bool isModified = false;
if (theFeature.get()) {
+ myIsActive[theFlag] = true;
+ myFeature = theFeature;
displayPresentation(theFlag, theUpdateViewer);
isModified = true;
}
Events_Loop::loop()->eventByName(Config_FeatureMessage::GUI_EVENT())) {
std::shared_ptr<Config_FeatureMessage> aFeatureMsg =
std::dynamic_pointer_cast<Config_FeatureMessage>(theMessage);
- if (!aFeatureMsg->isInternal()) {
- ActionInfo aFeatureInfo;
- aFeatureInfo.initFrom(aFeatureMsg);
- // Remember features icons
- myIcons[QString::fromStdString(aFeatureMsg->id())] = aFeatureInfo.iconFile;
- }
+ ActionInfo aFeatureInfo;
+ aFeatureInfo.initFrom(aFeatureMsg);
+ // Remember features icons
+ myIcons[QString::fromStdString(aFeatureMsg->id())] = aFeatureInfo.iconFile;
}
}
\ No newline at end of file
#include <ModuleBase_ISelection.h>
#include <ModuleBase_Operation.h>
-#include <ModuleBase_OperationAction.h>
#include <ModuleBase_OperationFeature.h>
#include <ModuleBase_ViewerPrs.h>
#include <ModuleBase_Tools.h>
XGUI_Workshop* aWorkshop = aConnector->workshop();
ModuleBase_Operation* anOperation = myModule->workshop()->currentOperation();
- ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(
- tr("Detach %1").arg(aLine->data()->name().c_str()), myModule);
+ ModuleBase_Operation* anOpAction =
+ new ModuleBase_Operation(tr("Detach %1").arg(aLine->data()->name().c_str()), myModule);
bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation);
XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
// the active nested sketch operation should be aborted unconditionally
QAction* anAction = action("AUXILIARY_CMD");
//SessionPtr aMgr = ModelAPI_Session::get();
- ModuleBase_OperationAction* anOpAction = 0;
+ ModuleBase_Operation* anOpAction = 0;
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
XGUI_OperationMgr* anOpMgr = aConnector->workshop()->operationMgr();
if (isUseTransaction) {
- anOpAction = new ModuleBase_OperationAction(anAction->text(), myModule);
+ anOpAction = new ModuleBase_Operation(anAction->text(), myModule);
bool isSketchOp = PartSet_SketcherMgr::isSketchOperation(anOperation);
bool isCommitted;
anOpMgr->startOperation(anOpAction);
}
+ static const Events_ID anVisualEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES);
if (anObjects.size() > 0) {
QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
for (; anIt != aLast; anIt++) {
aSketchFeature->data()->attribute(anAttribute));
if (anAuxiliaryAttr)
anAuxiliaryAttr->setValue(isChecked);
+ ModelAPI_EventCreator::get()->sendUpdated(aSketchFeature, anVisualEvent);
}
}
}
anOpMgr->commitOperation();
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ Events_Loop::loop()->flush(anVisualEvent);
}
bool PartSet_MenuMgr::canSetAuxiliary(bool& theValue) const
#include <SketchPlugin_ConstraintCoincidence.h>
#include <ModuleBase_Operation.h>
-#include <ModuleBase_OperationAction.h>
#include <ModuleBase_IViewer.h>
#include <ModuleBase_IViewWindow.h>
#include <ModuleBase_IPropertyPanel.h>
#include <ModuleBase_WidgetFactory.h>
#include <ModuleBase_OperationDescription.h>
#include <ModuleBase_ViewerPrs.h>
-#include <ModelAPI_ResultField.h>
+#include <ModuleBase_ResultPrs.h>
+#include <ModelAPI_ResultField.h>
#include <ModelAPI_Object.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Tools.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_ResultGroup.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomDataAPI_Point.h>
#include <XGUI_ActiveControlSelector.h>
#include <XGUI_ActionsMgr.h>
#include <XGUI_ContextMenuMgr.h>
-#include <XGUI_CustomPrs.h>
#include <XGUI_DataModel.h>
#include <XGUI_Displayer.h>
#include <XGUI_ErrorMgr.h>
setDefaultConstraintShown();
+ //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
+ // Config_Prop::Color, "225,225,225");
+
+ Config_PropManager::registerProp("Visualization", "result_body_color", "Result color",
+ Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR());
+
+ Config_PropManager::registerProp("Visualization", "result_group_color", "Group color",
+ Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR());
+
+ Config_PropManager::registerProp("Visualization", "result_construction_color",
+ "Construction color",
+ Config_Prop::Color,
+ ModelAPI_ResultConstruction::DEFAULT_COLOR());
+
+ Config_PropManager::registerProp("Visualization", "result_part_color", "Part color",
+ Config_Prop::Color, ModelAPI_ResultPart::DEFAULT_COLOR());
+
+ Config_PropManager::registerProp("Visualization", "result_field_color", "Field color",
+ Config_Prop::Color, ModelAPI_ResultField::DEFAULT_COLOR());
+
Config_PropManager::registerProp("Visualization", "operation_parameter_color",
"Reference shape wireframe color in operation", Config_Prop::Color,
PartSet_CustomPrs::OPERATION_PARAMETER_COLOR());
Config_PropManager::registerProp("Visualization", "sketch_dimension_color",
"Dimension color",
Config_Prop::Color, SKETCH_DIMENSION_COLOR);
+
+ Config_PropManager::registerProp("Shortcuts", "add_parameter_shortcut",
+ "Add parameter in parameters manager dialog",
+ Config_Prop::Shortcut, "Ctrl+A");
+
+ Config_PropManager::registerProp("Windows", "use_hide_faces_panel",
+ "Use HideFaces panel in operations", Config_Prop::Boolean, "false");
}
//******************************************************
if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
mySketchMgr->startSketch(theOperation);
}
- else if (sketchMgr()->isNestedSketchOperation(theOperation)) {
- mySketchMgr->startNestedSketch(theOperation);
- }
+ // It is switched off because of
+ // Task #3067: 5.2.2 Drawing in the sketcher: change the mouse cursor arrow
+ //else if (sketchMgr()->isNestedSketchOperation(theOperation)) {
+ // mySketchMgr->startNestedSketch(theOperation);
+ //}
}
//******************************************************
bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& theActionId) const
{
bool aValid = true;
- if (theActionId == "MOVE_CMD") {
+ if (theActionId == "MOVE_CMD" || theActionId == "MOVE_SPLIT_CMD") {
FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
if (aFeature) {
ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
}
//******************************************************
-bool PartSet_Module::createWidgets(ModuleBase_Operation* theOperation,
+bool PartSet_Module::createWidgets(const FeaturePtr& theFeature, const QString& theXmlRepr,
QList<ModuleBase_ModelWidget*>& theWidgets) const
{
bool aProcessed = false;
- ModuleBase_OperationFeature* aFOperation =
- dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
XGUI_Workshop* aWorkshop = getWorkshop();
XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
- if (mySketchMgr->activeSketch().get() && aFOperation && aPropertyPanel) {
+ if (mySketchMgr->activeSketch().get() && aPropertyPanel) {
ModuleBase_ISelection* aSelection = workshop()->selection();
// click on a point in sketch leads here with the point is highlighted, not yet selected
QList<ModuleBase_ViewerPrsPtr> aPreselection = aSelection->getHighlighted();
ObjectPtr anObject = aSelectedPrs->object();
FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
- FeaturePtr anOpFeature = aFOperation->feature();
GeomShapePtr aShape = aSelectedPrs->shape();
// click on the digit of dimension constrain comes here
// with an empty shape, so we need the check
- if (aFeature == anOpFeature && aShape.get() && !aShape->isNull()) {
+ if (aFeature == theFeature && aShape.get() && !aShape->isNull()) {
// if feature has only one result and shape of result is equal to selected shape
// this attribute is not processed. It is a case of Sketch Point.
if (aFeature->results().size() == 1) {
AttributePtr anAttribute = PartSet_Tools::findAttributeBy2dPoint(anObject, aTDShape,
mySketchMgr->activeSketch());
if (anAttribute.get()) {
- QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
- ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), workshop());
+ ModuleBase_WidgetFactory aFactory(theXmlRepr.toStdString(), workshop());
const std::string anAttributeId = anAttribute->id();
aFactory.createWidget(aPropertyPanel->contentWidget(), anAttributeId);
// 3. start operation
QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
- ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, this);
+ ModuleBase_Operation* anOpAction = new ModuleBase_Operation(aDescription, this);
// the active nested sketch operation should be aborted unconditionally
// the Delete action should be additionally granted for the Sketch operation
}
//******************************************************
-bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
- std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs)
-{
- bool aCustomized = false;
-
- XGUI_Workshop* aWorkshop = getWorkshop();
- XGUI_Displayer* aDisplayer = aWorkshop->displayer();
- ObjectPtr anObject = aDisplayer->getObject(thePrs);
- if (!anObject)
- return aCustomized;
-
- if (!theResult.get()) {
- std::vector<int> aColor;
- XGUI_CustomPrs::getDefaultColor(anObject, true, aColor);
- if (!aColor.empty()) {
- aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
- }
- }
- // customize dimentional constrains
- sketchMgr()->customizePresentation(anObject);
-
- return aCustomized;
-}
-
-//******************************************************
-bool PartSet_Module::afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
- AISObjectPtr thePrs,
- GeomCustomPrsPtr theCustomPrs)
-{
- bool aCustomized = false;
-
- XGUI_Workshop* aWorkshop = getWorkshop();
- XGUI_Displayer* aDisplayer = aWorkshop->displayer();
- ObjectPtr anObject = aDisplayer->getObject(thePrs);
- if (!anObject)
- return aCustomized;
-
- std::vector<int> aColor;
- bool aUseCustomColor = true;
- if (aUseCustomColor)
- myOverconstraintListener->getCustomColor(anObject, aColor);
- // customize sketch symbol presentation
- Handle(AIS_InteractiveObject) anAISIO = thePrs->impl<Handle(AIS_InteractiveObject)>();
- if (!anAISIO.IsNull()) {
- if (!Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO).IsNull()) {
- Handle(SketcherPrs_SymbolPrs) aPrs = Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO);
- if (!aPrs.IsNull()) {
- aPrs->SetCustomColor(aColor);
- aCustomized = true;
- }
- } else if (!Handle(SketcherPrs_Coincident)::DownCast(anAISIO).IsNull()) {
- Handle(SketcherPrs_Coincident) aPrs = Handle(SketcherPrs_Coincident)::DownCast(anAISIO);
- if (!aPrs.IsNull()) {
- aPrs->SetCustomColor(aColor);
- aCustomized = true;
- }
- }
- }
- // customize sketch dimension constraint presentation
- if (!aCustomized) {
- if (!aColor.empty()) { // otherwise presentation has the default color
- aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
- }
- }
- return aCustomized;
-}
-
-//******************************************************
-bool PartSet_Module::customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
+//bool PartSet_Module::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
+// std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs)
+//{
+// bool aCustomized = false;
+//
+// XGUI_Workshop* aWorkshop = getWorkshop();
+// XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+// ObjectPtr anObject = aDisplayer->getObject(thePrs);
+// if (!anObject)
+// return aCustomized;
+//
+// if (!theResult.get()) {
+// std::vector<int> aColor;
+// XGUI_CustomPrs::getDefaultColor(anObject, true, aColor);
+// if (!aColor.empty()) {
+// aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+// }
+// }
+// // customize dimentional constrains
+// sketchMgr()->customisePresentation(anObject);
+//
+// return aCustomized;
+//}
+//
+////******************************************************
+//bool PartSet_Module::afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+// AISObjectPtr thePrs,
+// GeomCustomPrsPtr theCustomPrs)
+//{
+// bool aCustomized = false;
+//
+// XGUI_Workshop* aWorkshop = getWorkshop();
+// XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+// ObjectPtr anObject = aDisplayer->getObject(thePrs);
+// if (!anObject)
+// return aCustomized;
+//
+// std::vector<int> aColor;
+// bool aUseCustomColor = true;
+// if (aUseCustomColor)
+// myOverconstraintListener->getCustomColor(anObject, aColor);
+// // customize sketch symbol presentation
+// Handle(AIS_InteractiveObject) anAISIO = thePrs->impl<Handle(AIS_InteractiveObject)>();
+// if (!anAISIO.IsNull()) {
+// if (!Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO).IsNull()) {
+// Handle(SketcherPrs_SymbolPrs) aPrs = Handle(SketcherPrs_SymbolPrs)::DownCast(anAISIO);
+// if (!aPrs.IsNull()) {
+// aPrs->SetCustomColor(aColor);
+// aCustomized = true;
+// }
+// } else if (!Handle(SketcherPrs_Coincident)::DownCast(anAISIO).IsNull()) {
+// Handle(SketcherPrs_Coincident) aPrs = Handle(SketcherPrs_Coincident)::DownCast(anAISIO);
+// if (!aPrs.IsNull()) {
+// aPrs->SetCustomColor(aColor);
+// aCustomized = true;
+// }
+// }
+// }
+// // customize sketch dimension constraint presentation
+// if (!aCustomized) {
+// if (!aColor.empty()) { // otherwise presentation has the default color
+// aCustomized = thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+// }
+// }
+// return aCustomized;
+//}
+
+//******************************************************
+bool PartSet_Module::customizeFeature(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
const bool theUpdateViewer)
{
bool isRedisplayed = false;
}
//******************************************************
-Handle(AIS_InteractiveObject) PartSet_Module::createPresentation(const ObjectPtr& theObject)
+AISObjectPtr PartSet_Module::createPresentation(const ObjectPtr& theObject)
+{
+ Handle(AIS_InteractiveObject) anAISPrs = mySketchMgr->createPresentation(theObject);
+ if (anAISPrs.IsNull()) {
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+ if (aResult.get()) {
+ std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
+ if (aShapePtr.get() != NULL)
+ anAISPrs = new ModuleBase_ResultPrs(aResult);
+ }
+ else {
+ FieldStepPtr aStep =
+ std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(theObject);
+ if (aStep.get()) {
+ anAISPrs = new PartSet_FieldStepPrs(aStep);
+ }
+ }
+ }
+ AISObjectPtr anAIS;
+ if (!anAISPrs.IsNull()) {
+ Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
+ if (!aShapePrs.IsNull())
+ ModuleBase_Tools::setPointBallHighlighting((AIS_Shape*)aShapePrs.get());
+
+ anAIS = AISObjectPtr(new GeomAPI_AISObject());
+ anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs));
+ customizePresentation(theObject, anAIS);
+ }
+ return anAIS;
+}
+
+//******************************************************
+void getResultColor(const ResultPtr& theResult, std::vector<int>& theColor)
+{
+ ModelAPI_Tools::getColor(theResult, theColor);
+ if (theColor.empty())
+ PartSet_Tools::getDefaultColor(theResult, false, theColor);
+}
+
+//******************************************************
+double getResultDeflection(const ResultPtr& theResult)
{
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
- if (aResult.get())
- return mySketchMgr->createPresentation(aResult);
+ double aDeflection = ModelAPI_Tools::getDeflection(theResult);
+ if (aDeflection < 0)
+ aDeflection = PartSet_Tools::getDefaultDeflection(theResult);
+ return aDeflection;
+}
+
+//******************************************************
+double getResultTransparency(const ResultPtr& theResult)
+{
+ double aTransparency = ModelAPI_Tools::getTransparency(theResult);
+ if (aTransparency < 0)
+ aTransparency = PartSet_Tools::getDefaultTransparency();
+ return aTransparency;
+}
+
+
+//******************************************************
+void PartSet_Module::customizePresentation(const ObjectPtr& theObject,
+ const AISObjectPtr& thePrs) const
+{
+ if (mySketchMgr->isObjectOfSketch(theObject)) {
+ mySketchMgr->customizeSketchPresentation(theObject, thePrs);
+ }
else {
- FieldStepPtr aStep =
- std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(theObject);
- if (aStep.get()) {
- return new PartSet_FieldStepPrs(aStep);
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+ if (aResult.get()) {
+ std::vector<int> aColor;
+ getResultColor(aResult, aColor);
+
+ SessionPtr aMgr = ModelAPI_Session::get();
+ if (aMgr->activeDocument() != aResult->document()) {
+ QColor aQColor(aColor[0], aColor[1], aColor[2]);
+ QColor aNewColor =
+ QColor::fromHsvF(aQColor.hueF(), aQColor.saturationF() / 3., aQColor.valueF());
+ aColor[0] = aNewColor.red();
+ aColor[1] = aNewColor.green();
+ aColor[2] = aNewColor.blue();
+ }
+ thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+
+ thePrs->setDeflection(getResultDeflection(aResult));
+
+ thePrs->setTransparency(getResultTransparency(aResult));
+ }
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+ if (aFeature.get()) {
+ if (aFeature->getKind() == SketchPlugin_Sketch::ID())
+ thePrs->setWidth(2);
}
}
- return Handle(AIS_InteractiveObject)();
}
+
//******************************************************
ObjectPtr PartSet_Module::findPresentedObject(const AISObjectPtr& theAIS) const
{
/// If there is found selected attribute, widgets are created and contains
/// only a widget for the attribute
/// It is important for Property Panel filling by sketch point attribute
- /// \param theOperation a started operation
+ /// \param theFeature a feature of the started operation
+ /// \param theXmlRepr an XML representation of the operation
/// \param theWidgets a list of created widgets
/// \return boolean result, false by default
- virtual bool createWidgets(ModuleBase_Operation* theOperation,
+ virtual bool createWidgets(const FeaturePtr& theFeature, const QString& theXmlRepr,
QList<ModuleBase_ModelWidget*>& theWidgets) const;
/// Launching of a edit operation on the feature
const bool theUpdateViewer);
/// Modifies the given presentation in the custom way.
- virtual bool customisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
- AISObjectPtr thePrs,
- std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs);
+ //virtual bool customisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+ // AISObjectPtr thePrs,
+ // std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs);
- /// Modifies the given presentation in the custom way after usual customize is performed.
- virtual bool afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
- AISObjectPtr thePrs,
- GeomCustomPrsPtr theCustomPrs);
+ ///// Modifies the given presentation in the custom way after usual customize is performed.
+ //virtual bool afterCustomisePresentation(std::shared_ptr<ModelAPI_Result> theResult,
+ // AISObjectPtr thePrs,
+ // GeomCustomPrsPtr theCustomPrs);
/// Update the object presentable properties such as color, lines width and other
/// If the object is result with the color attribute value set, it is used,
/// should be updated(e.g. only highlighted elements)
/// \param theUpdateViewer the parameter whether the viewer should be update immediatelly
/// \returns true if the object is modified
- virtual bool customizeObject(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
- const bool theUpdateViewer);
+ virtual bool customizeFeature(ObjectPtr theObject, const ModuleBase_CustomizeFlag& theFlag,
+ const bool theUpdateViewer);
/// Disable displaying of custom mode
/// \param theMode a mode to disable
/// Create specific for the module presentation
/// \param theResult an object for presentation
/// \return created presentation or NULL(default value)
- virtual Handle(AIS_InteractiveObject) createPresentation(const ObjectPtr& theResult);
+ virtual AISObjectPtr createPresentation(const ObjectPtr& theResult);
+
+ /// Customize presentation according to objects attributes
+ /// \param theObject an object for presentation
+ /// \param thePrs a presentation object
+ virtual void customizePresentation(const ObjectPtr& theObject, const AISObjectPtr& thePrs) const;
//! Returns data object by AIS
virtual ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const;
#include <PartSet_SketcherMgr.h>
#include <PartSet_SketcherReentrantMgr.h>
-#include "XGUI_CustomPrs.h"
#include "XGUI_Displayer.h"
#include "XGUI_ModuleConnector.h"
#include "XGUI_OperationMgr.h"
{
static Events_Loop* aLoop = Events_Loop::loop();
- static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_VISUAL_ATTRIBUTES);
static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
/// Redefinition of Events_Listener method
virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ bool isConflictingObject(const ObjectPtr& theObject) const
+ {
+ return (myConflictingObjects.find(theObject) != myConflictingObjects.end());
+ }
+
+ bool isFullyConstrained() const { return myIsFullyConstrained; }
+
protected:
/// Append objects to the internal container of conflicting object, redisplay necessary objects
/// \param theObjects a list of new conflicting objects
#include <QMessageBox>
#include <QMainWindow>
+#include <set>
+
//#define DEBUG_DO_NOT_BY_ENTER
//#define DEBUG_SKETCHER_ENTITIES
//#define DEBUG_SKETCH_ENTITIES_ON_MOVE
registerSelectionFilter(SF_SketchCirclePointFilter, new PartSet_CirclePointFilter(anIWorkshop));
registerSelectionFilter(SF_SketchPlaneFilter, new ModuleBase_ShapeInPlaneFilter());
+
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_DOF_OBJECTS));
}
PartSet_SketcherMgr::~PartSet_SketcherMgr()
return;
#endif
- if (canChangeCursor(getCurrentOperation())) {
- QCursor* aCurrentCursor = QApplication::overrideCursor();
- if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
- QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
-#ifdef DEBUG_CURSOR
- qDebug("onEnterViewPort() : Qt::CrossCursor");
-#endif
- }
- }
+ // It is switched off because of
+ // Task #3067: 5.2.2 Drawing in the sketcher: change the mouse cursor arrow
+ // if (canChangeCursor(getCurrentOperation())) {
+ // QCursor* aCurrentCursor = QApplication::overrideCursor();
+ // if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
+ // QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+ //#ifdef DEBUG_CURSOR
+ // qDebug("onEnterViewPort() : Qt::CrossCursor");
+ //#endif
+ // }
+ // }
if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
return;
return;
#endif
- if (canChangeCursor(getCurrentOperation())) {
- QApplication::restoreOverrideCursor();
-#ifdef DEBUG_CURSOR
- qDebug("onLeaveViewPort() : None");
-#endif
- }
+// if (canChangeCursor(getCurrentOperation())) {
+// QApplication::restoreOverrideCursor();
+//#ifdef DEBUG_CURSOR
+// qDebug("onLeaveViewPort() : None");
+//#endif
+// }
if (!isNestedCreateOperation(getCurrentOperation(), activeSketch()))
return;
}
// Init flyout point for radius rotation
FeaturePtr aFeature = myCurrentSelection.begin().key();
-
get2dPoint(theWnd, theEvent, myCurrentPoint);
if (isSketcher) {
if (aCanDrag) {
/// Internal edit should not be stored as editing operation as the result will be a
/// creation operation, where previous selection should not be used(and will be cleared)
myIsEditLaunching = !myModule->sketchReentranceMgr()->isInternalEditActive();
- aFOperation->commit();
+
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFOperation->feature());
+ bool isRelaunchEditing = true;
+ if (aSPFeature->isExternal()) {
+ foreach(FeaturePtr aF, myCurrentSelection.keys()) {
+ FeaturePtr aProducerFeature = PartSet_Tools::findRefsToMeFeature(aF,
+ aSPFeature->getKind());
+ if (aProducerFeature == aSPFeature) {
+ isRelaunchEditing = false;
+ break;
+ }
+ }
+ }
+ else
+ isRelaunchEditing = !myCurrentSelection.contains(aSPFeature);
+
+ if (isRelaunchEditing)
+ aFOperation->commit();
if (aCanDrag) {
myIsDragging = true;
myDragDone = false;
}
myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
- launchEditing();
+ if (isRelaunchEditing)
+ launchEditing();
myIsEditLaunching = aPrevLaunchingState;
if (aFeature.get() != NULL) {
std::shared_ptr<SketchPlugin_Feature> aSPFeature =
void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
{
ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+ ModuleBase_IViewer* aViewer = aWorkshop->viewer();
if (myIsDragging)
- aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
+ aViewer->enableDrawMode(myPreviousDrawModeEnabled);
bool aWasDragging = myIsDragging;
myIsDragging = false;
if (!myIsMouseOverViewProcessed) {
return;
}
- ModuleBase_IViewer* aViewer = aWorkshop->viewer();
//if (!aViewer->canDragByMouse())
// return;
ModuleBase_OperationFeature* aOp =
- dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
+ dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
if (aOp) {
bool aStartNoDragOperation = !aViewer->canDragByMouse() && aOp->isEditOperation();
if (aStartNoDragOperation || myNoDragMoving) {
theModes.append(TopAbs_EDGE);
}
-Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ResultPtr& theResult)
+Handle(AIS_InteractiveObject) PartSet_SketcherMgr::createPresentation(const ObjectPtr& theObj)
{
Handle(AIS_InteractiveObject) aPrs;
- FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObj);
if (aFeature.get() && aFeature->getKind() == SketchPlugin_Sketch::ID()) {
- aPrs = new PartSet_ResultSketchPrs(theResult);
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObj);
+ if (aResult.get())
+ aPrs = new PartSet_ResultSketchPrs(aResult);
}
return aPrs;
}
(theId == SketchPlugin_Arc::ID()) ||
(theId == SketchPlugin_Circle::ID()) ||
(theId == SketchPlugin_Ellipse::ID()) ||
+ (theId == SketchPlugin_Projection::ID()) ||
+ (theId == SketchPlugin_IntersectionPoint::ID()) ||
(theId == SketchPlugin_EllipticArc::ID());
}
void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation)
{
+ static Events_ID EVENT_ATTR = Events_Loop::loop()->eventByName(EVENT_VISUAL_ATTRIBUTES);
+ static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
(getCurrentOperation());
if (!aFOperation)
myModule->overconstraintListener()->setActive(true);
// Display sketcher objects
QStringList anInfo;
- Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
aNumberOfSubs = myCurrentSketch->numberOfSubs();
for (int i = 0; i < aNumberOfSubs; i++) {
aECreator->sendUpdated(aFeature, EVENT_DISP);
else
aFeature->setDisplayed(true);
+ aECreator->sendUpdated(aFeature, EVENT_ATTR);
}
#ifdef DEBUG_SKETCHER_ENTITIES
QString anInfoStr = anInfo.join(";\t");
workshop()->selectionActivate()->updateSelectionFilters();
workshop()->selectionActivate()->updateSelectionModes();
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ Events_Loop::loop()->flush(EVENT_DISP);
+ Events_Loop::loop()->flush(EVENT_ATTR);
myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
workshop()->viewer()->set2dMode(false);
}
-void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
-{
- if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
- QCursor* aCurrentCursor = QApplication::overrideCursor();
- if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
- QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
-#ifdef DEBUG_CURSOR
- qDebug("startNestedSketch() : Qt::CrossCursor");
-#endif
- }
- }
-}
+//void PartSet_SketcherMgr::startNestedSketch(ModuleBase_Operation* theOperation)
+//{
+// if (canChangeCursor(theOperation) && myIsMouseOverWindow) {
+// QCursor* aCurrentCursor = QApplication::overrideCursor();
+// if (!aCurrentCursor || aCurrentCursor->shape() != Qt::CrossCursor) {
+// QApplication::setOverrideCursor(QCursor(Qt::CrossCursor));
+//#ifdef DEBUG_CURSOR
+// qDebug("startNestedSketch() : Qt::CrossCursor");
+//#endif
+// }
+// }
+//}
void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOperation)
{
operationMgr()->onValidateOperation();
// when sketch nested operation is stopped the cursor should be restored unconditionally
//if (canChangeCursor(theOperation)) {
- QApplication::restoreOverrideCursor();
+ //QApplication::restoreOverrideCursor();
#ifdef DEBUG_CURSOR
qDebug("stopNestedSketch() : None");
#endif
bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
{
- bool isFoundObject = false;
-
+ if (!myCurrentSketch.get())
+ return false;
FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
if (anObjectFeature.get()) {
int aSize = myCurrentSketch->numberOfSubs();
- for (int i = 0; i < aSize && !isFoundObject; i++) {
- FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);
- isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;
+ FeaturePtr aCurrentFeature;
+ for (int i = 0; i < aSize; i++) {
+ aCurrentFeature = myCurrentSketch->subFeature(i);
+ if (myCurrentSketch->subFeature(i) == anObjectFeature)
+ return true;
}
}
- return isFoundObject;
+ return false;
}
void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePlane)
}
}
-void PartSet_SketcherMgr::customizePresentation(const ObjectPtr& theObject)
-{
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
- isNestedSketchOperation(aFOperation)))
- SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
-
- // update entities selection priorities
- FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
- // update priority for feature
- updateSelectionPriority(aFeature, aFeature);
- // update priority for results of the feature
- std::list<ResultPtr> aResults = aFeature->results();
- std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLastIt = aResults.end();
- for (; anIt != aLastIt; anIt++)
- updateSelectionPriority(*anIt, aFeature);
- }
-}
+//void PartSet_SketcherMgr::customisePresentation(const ObjectPtr& theObject)
+//{
+// ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+// (getCurrentOperation());
+// if (aFOperation && (PartSet_SketcherMgr::isSketchOperation(aFOperation) ||
+// isNestedSketchOperation(aFOperation)))
+// SketcherPrs_Tools::sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
+//
+// // update entities selection priorities
+// FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+// if (aFeature.get() && PartSet_SketcherMgr::isEntity(aFeature->getKind())) {
+// // update priority for feature
+// updateSelectionPriority(aFeature, aFeature);
+// // update priority for results of the feature
+// std::list<ResultPtr> aResults = aFeature->results();
+// std::list<ResultPtr>::const_iterator anIt = aResults.begin(), aLastIt = aResults.end();
+// for (; anIt != aLastIt; anIt++)
+// updateSelectionPriority(*anIt, aFeature);
+// }
+//}
ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const
{
if (aPrevState != theState) {
/// call all sketch features redisplay, the expression state will be corrected in customize
/// of distance presentation
+ SketcherPrs_Tools::
+ sendExpressionShownEvent(myIsConstraintsShown[PartSet_Tools::Expressions]);
Events_ID anEventId = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
PartSet_Tools::sendSubFeaturesEvent(myCurrentSketch, anEventId);
}
aViewer->update();
}
+void PartSet_SketcherMgr::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+ if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_DOF_OBJECTS)) {
+ std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ std::set<ObjectPtr> aObjects = anUpdateMsg->objects();
+ std::set<ObjectPtr>::const_iterator aIt;
+ QList<ModuleBase_ViewerPrsPtr> aPrsList;
+ for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*aIt);
+ if (aFeature.get()) {
+ std::list<ResultPtr> aRes = aFeature->results();
+ std::list<ResultPtr>::const_iterator aIt;
+ for (aIt = aRes.cbegin(); aIt != aRes.cend(); ++aIt) {
+ ModuleBase_ViewerPrsPtr aPrsPtr(new ModuleBase_ViewerPrs(*aIt));
+ aPrsList.append(aPrsPtr);
+ }
+ }
+ }
+ if (aPrsList.size() > 0) {
+ myModule->workshop()->setSelected(aPrsList);
+ }
+ }
+}
+
+bool isExternal(const ObjectPtr& theObject)
+{
+ AttributeSelectionPtr aAttr =
+ theObject->data()->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
+ if (aAttr)
+ return aAttr->context().get() != NULL && !aAttr->isInvalid();
+ return false;
+}
+
+bool isCopy(const ObjectPtr& theObject)
+{
+ AttributeBooleanPtr anAttr = theObject->data()->boolean(SketchPlugin_SketchEntity::COPY_ID());
+ if (anAttr.get())
+ return anAttr->value();
+ return false;
+}
+
+bool isIncludeToResult(const ObjectPtr& theObject)
+{
+ AttributeBooleanPtr anAttr;
+ std::set<AttributePtr> aRefsToMe = theObject->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aIt;
+ for (aIt = aRefsToMe.cbegin(); aIt != aRefsToMe.cend(); ++aIt) {
+ if ((*aIt)->id() == SketchPlugin_Projection::PROJECTED_FEATURE_ID()) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
+ if (aFeature.get()) {
+ anAttr = aFeature->data()->boolean(SketchPlugin_Projection::INCLUDE_INTO_RESULT());
+ if (anAttr.get())
+ return anAttr->value();
+ }
+ }
+ }
+ return true;
+}
+
+//**************************************************************************************
+std::vector<int> PartSet_SketcherMgr::colorOfObject(const ObjectPtr& theObject,
+ const FeaturePtr& theFeature, bool isConstruction) const
+{
+ static const QStringList& aConstrIds = constraintsIdList();
+ PartSet_OverconstraintListener* aOCListener = myModule->overconstraintListener();
+ std::string aKind = theFeature->getKind();
+
+ if (isDistanceKind(aKind)) {
+ if (aOCListener->isConflictingObject(theObject))
+ return Config_PropManager::color("Visualization", "sketch_overconstraint_color");
+ return Config_PropManager::color("Visualization", "sketch_dimension_color");
+ }
+ if (isExternal(theFeature))
+ return Config_PropManager::color("Visualization", "sketch_external_color");
+ if (isConstruction)
+ return Config_PropManager::color("Visualization", "sketch_auxiliary_color");
+
+ if (aOCListener->isFullyConstrained()) {
+ return Config_PropManager::color("Visualization", "sketch_fully_constrained_color");
+ }
+ else if (aOCListener->isConflictingObject(theObject)) {
+ return Config_PropManager::color("Visualization", "sketch_overconstraint_color");
+ }
+ return Config_PropManager::color("Visualization", "sketch_entity_color");
+}
+
+//**************************************************************************************
+void PartSet_SketcherMgr::customizeSketchPresentation(const ObjectPtr& theObject,
+ const AISObjectPtr& thePrs) const
+{
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+
+ // set color from preferences
+ std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
+ aFeature->data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
+ bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
+
+ std::vector<int> aColor = colorOfObject(theObject, aFeature, isConstruction);
+ if (!aColor.empty()) {
+ // The code below causes redisplay again
+ if (ModelAPI_Session::get()->isOperation()) {
+ AttributeIntArrayPtr aColorAttr = theObject->data()->intArray(ModelAPI_Result::COLOR_ID());
+ if (aColorAttr.get()) {
+ aColorAttr->setSize(3, false);
+ // Set the color attribute in order do not use default colors in the presentation object
+ for (int i = 0; i < 3; i++)
+ aColorAttr->setValue(i, aColor[i], false);
+ }
+ }
+ thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+ }
+
+ int aShapeType = thePrs->getShapeType();
+ // a compound is processed like the edge because the
+ // arc feature uses the compound for presentable AIS
+ if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/)
+ return;
+
+ if (isExternal(aFeature)) {
+ thePrs->setWidth(1);
+ return;
+ }
+ std::string aKind = aFeature->getKind();
+ if (isDistanceKind(aKind))
+ return;
+
+ if (aShapeType == 6 || aShapeType == 0) { // if this is an edge or a compound
+ if (isConstruction) {
+ // Set axilliary line
+ thePrs->setWidth(SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY());
+ thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
+ }
+ else {
+ int aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
+ thePrs->setWidth(aWidth);
+ thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
+ }
+ }
+ else if (aShapeType == 7) { // otherwise this is a vertex
+ // The width value do not have effect on the point presentation.
+ // It is defined in order to extend selection area of the object.
+ thePrs->setWidth(17);
+ // thePrs->setPointMarker(1, 1.); // Set point as a '+' symbol
+ }
+ if (isCopy(aFeature) && !isIncludeToResult(aFeature)) {
+ double aWidth = thePrs->width();
+ thePrs->setWidth(aWidth / 2.5);
+ }
+
+ double aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
+ thePrs->setDeflection(aDeflection);
+}
+//*************************************************************************************
void PartSet_Fitter::fitAll(Handle(V3d_View) theView)
{
CompositeFeaturePtr aSketch = mySketchMgr->activeSketch();
#include <ModelAPI_Attribute.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Result.h>
+#include <Events_Listener.h>
#include <ModuleBase_SelectionFilterType.h>
#include <ModuleBase_Definitions.h>
#include <ModuleBase_ModelWidget.h>
#include <GeomAPI_Pln.h>
+#include <GeomAPI_AISObject.h>
#ifdef HAVE_SALOME
#include <OCCViewer_ViewModel.h>
displayed in the viewer. After the sketch create/edit operation is finished, the sub-feature
are hidden, the sketch feature result is displayed
*/
-class PARTSET_EXPORT PartSet_SketcherMgr : public QObject
+class PARTSET_EXPORT PartSet_SketcherMgr : public QObject, public Events_Listener
{
Q_OBJECT
/// Struct to define gp point, with the state is the point is initialized
/// Starts sketch operation, connects to the opeation property panel
/// \param theOperation a committed operation
- void startNestedSketch(ModuleBase_Operation* theOperation);
+ //void startNestedSketch(ModuleBase_Operation* theOperation);
/// Stop sketch operation, disconnects from the opeation property panel
/// \param theOperation a stopped operation
/// Create specific for the module presentation
/// \param theResult an object for presentation
/// \return created presentation or NULL(default value)
- virtual Handle(AIS_InteractiveObject) createPresentation(const ResultPtr& theResult);
+ Handle(AIS_InteractiveObject) createPresentation(const ObjectPtr& theResult);
/// Connects or disconnects to the value changed signal of the property panel widgets
/// \param theWidget a property contol widget
/// If the current operation is a dimention one, the style of dimension visualization is send for
/// the current object
/// \param theObject an object to be customized
- void customizePresentation(const ObjectPtr& theObject);
+ //void customisePresentation(const ObjectPtr& theObject);
+
+ void customizeSketchPresentation(const ObjectPtr& theObject, const AISObjectPtr& thePrs) const;
/// Update sketch presentations according to the the state
/// \param theType a type of sketch visualization style
PartSet_Module* module() const { return myModule; }
+ /** \brief Implementation of Event Listener method
+ * \param[in] theMessage the data of the event
+ */
+ virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+
public slots:
/// Process sketch plane selected event
void onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln);
/// Returns operation manager
XGUI_OperationMgr* operationMgr() const;
+ std::vector<int> colorOfObject(const ObjectPtr& theObject,
+ const FeaturePtr& aFeature, bool isConstruction) const;
+
private:
PartSet_Module* myModule;
PartSet_PreviewSketchPlane* mySketchPlane; // display/erase sketch plane on start/stop sketch
#include <ModelGeomAlgo_Point2D.h>
#include <Events_Loop.h>
+#include <Events_InfoMessage.h>
#include <SketcherPrs_Tools.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Vertex.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <GeomAPI_Dir.h>
#include <GeomAPI_XYZ.h>
theFirst = aDoc->index(aFirstFeatureInFolder);
theLast = aDoc->index(aLastFeatureInFolder);
}
+
+
+void PartSet_Tools::getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
+ std::vector<int>& theColor)
+{
+ theColor.clear();
+ // get default color from the preferences manager for the given result
+ if (theColor.empty()) {
+ std::string aSection, aName, aDefault;
+ theObject->colorConfigInfo(aSection, aName, aDefault);
+ if (!aSection.empty() && !aName.empty()) {
+ theColor = Config_PropManager::color(aSection, aName);
+ }
+ }
+ if (!isEmptyColorValid && theColor.empty()) {
+ // all AIS objects, where the color is not set, are in black.
+ // The color should be defined in XML or set in the attribute
+ theColor = Config_PropManager::color("Visualization", "object_default_color");
+ Events_InfoMessage("PartSet_Tools",
+ "A default color is not defined in the preferences for this result type").send();
+ }
+}
+
+double PartSet_Tools::getDefaultDeflection(const ObjectPtr& theObject)
+{
+ double aDeflection = -1;
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+ if (aResult.get()) {
+ bool isConstruction = false;
+
+ std::string aResultGroup = aResult->groupName();
+ if (aResultGroup == ModelAPI_ResultConstruction::group())
+ isConstruction = true;
+ else if (aResultGroup == ModelAPI_ResultBody::group()) {
+ GeomShapePtr aGeomShape = aResult->shape();
+ if (aGeomShape.get()) {
+ // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
+ // correction of deviation for them should not influence to the application performance
+ GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
+ isConstruction = !anExp.more();
+ }
+ }
+ if (isConstruction)
+ aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
+ else
+ aDeflection = Config_PropManager::real("Visualization", "body_deflection");
+ }
+ return aDeflection;
+}
+
+
+double PartSet_Tools::getDefaultTransparency()
+{
+ return Config_PropManager::integer("Visualization", "shaper_default_transparency") / 100.;
+}
FeaturePtr& theCreatedFeature);
- static void getFirstAndLastIndexInFolder(const ObjectPtr& theFolder, int& theFirst, int& theLast);
+ static void getFirstAndLastIndexInFolder(const ObjectPtr& theFolder,
+ int& theFirst, int& theLast);
+
+
+ /**
+ * Returns default color value for the given object
+ */
+ static void getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
+ std::vector<int>& theColor);
+
+ /**
+ * Returns default deflection value for the given object
+ */
+ static double getDefaultDeflection(const ObjectPtr& theObject);
+
+
+ /**
+ * Returns default transparency value
+ */
+ static double getDefaultTransparency();
};
#endif
#include <ModuleBase_ISelection.h>
#include <ModuleBase_ViewerPrs.h>
+#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeReference.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_Feature.h>
std::string anAttributes = theData->getProperty("selection_attributes");
QStringList anAttributesList = QString(anAttributes.c_str()).split(' ', QString::SkipEmptyParts);
+ myHasPreview = anAttributesList.size() >= 4;
+
mySelectedObjectAttribute = anAttributesList[0].toStdString();
mySelectedPointAttribute = anAttributesList[1].toStdString();
- myPreviewObjectAttribute = anAttributesList[2].toStdString();
- myPreviewPointAttribute = anAttributesList[3].toStdString();
+ if (myHasPreview) {
+ myPreviewObjectAttribute = anAttributesList[2].toStdString();
+ myPreviewPointAttribute = anAttributesList[3].toStdString();
+ }
}
PartSet_WidgetFeaturePointSelector::~PartSet_WidgetFeaturePointSelector()
if (theEvent->button() != Qt::LeftButton)
return;
- std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- feature()->data()->attribute(myPreviewObjectAttribute));
- ObjectPtr aPreviewObject = aRefPreviewAttr->value();
+ ObjectPtr aPreviewObject;
+ GeomPnt2dPtr aPreviewPoint;
+ if (myHasPreview) {
+ std::shared_ptr<ModelAPI_AttributeReference> aRefPreviewAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+ feature()->data()->attribute(myPreviewObjectAttribute));
+ aPreviewObject = aRefPreviewAttr->value();
+
+ std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ feature()->data()->attribute(myPreviewPointAttribute));
+ aPreviewPoint = aPointPreviewAttr->pnt();
+ }
+ else {
+ aPreviewObject = myPreviewObject;
+ aPreviewPoint = myPreviewPoint;
+ }
+
// do not move focus from the current widget if the object is not highlighted/selected
if (!aPreviewObject.get())
return;
// set parameters of preview into parameters of selection in the feature
- std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- feature()->data()->attribute(mySelectedObjectAttribute));
- aRefSelectedAttr->setValue(aRefPreviewAttr->value());
-
std::shared_ptr<GeomDataAPI_Point2D> aPointSelectedAttr =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
feature()->data()->attribute(mySelectedPointAttribute));
- std::shared_ptr<GeomDataAPI_Point2D> aPointPreviewAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- feature()->data()->attribute(myPreviewPointAttribute));
- aPointSelectedAttr->setValue(aPointPreviewAttr->x(), aPointPreviewAttr->y());
+ aPointSelectedAttr->setValue(aPreviewPoint);
+
+ AttributeReferencePtr aRefSelectedAttr = feature()->reference(mySelectedObjectAttribute);
+ if (aRefSelectedAttr)
+ aRefSelectedAttr->setValue(aPreviewObject);
+ else {
+ AttributeRefAttrPtr aRefAttrSelectedAttr = feature()->refattr(mySelectedObjectAttribute);
+ if (aRefAttrSelectedAttr)
+ aRefAttrSelectedAttr->setObject(aPreviewObject);
+ }
updateObject(feature());
QMouseEvent* theEvent)
{
bool aFilled = false;
- ObjectPtr anObject;
if (theSelectedPrs.get() && theSelectedPrs->object().get())
- anObject = theSelectedPrs->object();
-
- std::shared_ptr<ModelAPI_AttributeReference> aRef =
- std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- feature()->data()->attribute(myPreviewObjectAttribute));
- aRef->setValue(anObject);
-
- std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- feature()->data()->attribute(myPreviewPointAttribute));
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, mySketch);
- anAttributePoint->setValue(aPoint);
+ myPreviewObject = theSelectedPrs->object();
+ myPreviewPoint = PartSet_Tools::getPnt2d(theEvent, theWindow, mySketch);
+
+ if (myHasPreview) {
+ std::shared_ptr<ModelAPI_AttributeReference> aRef =
+ std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+ feature()->data()->attribute(myPreviewObjectAttribute));
+ aRef->setValue(myPreviewObject);
+
+ std::shared_ptr<GeomDataAPI_Point2D> anAttributePoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ feature()->data()->attribute(myPreviewPointAttribute));
+ anAttributePoint->setValue(myPreviewPoint);
+ }
// redisplay AIS presentation in viewer
#ifndef HIGHLIGHT_STAYS_PROBLEM
// an attempt to clear highlighted item in the viewer: but of OCCT
class ModuleBase_ViewerPrs;
class GeomAPI_Pnt;
+class GeomAPI_Pnt2d;
class GeomDataAPI_Point2D;
class QWidget;
std::string mySelectedPointAttribute;
std::string myPreviewObjectAttribute;
std::string myPreviewPointAttribute;
+
+ bool myHasPreview;
+ std::shared_ptr<ModelAPI_Object> myPreviewObject;
+ std::shared_ptr<GeomAPI_Pnt2d> myPreviewPoint;
};
#endif
\ No newline at end of file
/// \return a boolean value
virtual bool isValidSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& theValue);
+ /// Returns True in case if the widget contains useful information for inspection tool
+ virtual bool isInformative() const { return false; }
+
protected:
/// If there is no operation in current session, start operation for modify parameters
/// \return true if the operation was not opened
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_Tools.h>
#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Events.h>
#include <ModuleBase_Operation.h>
#include <ModuleBase_ViewerPrs.h>
#include <QCheckBox>
#include <QGroupBox>
#include <QPushButton>
-#include <QStackedWidget>
#include <QLineEdit>
#include <QDoubleValidator>
+#include <QDialog>
+#include <QTimer>
#ifndef DBL_MAX
#define DBL_MAX 1.7976931348623158e+308
mySizeOfView->setValidator(aValidator);
aSizeLayout->addWidget(mySizeOfView);
+ myPartSetMessage = new QDialog(this, Qt::ToolTip);
+ myPartSetMessage->setModal(false);
+ myPartSetMessage->setStyleSheet("background-color:lightyellow;");
+ QVBoxLayout* aMsgLay = new QVBoxLayout(myPartSetMessage);
+ QString aMsg = tr("The Sketch is created in PartSet.\n"
+ "It will be necessary to create a Part in order to use this sketch for body creation");
+ aMsgLay->addWidget(new QLabel(aMsg, myPartSetMessage));
+ myPartSetMessage->hide();
+
+ mySizeMessage = new QDialog(mySizeOfView, Qt::ToolTip);
+ mySizeMessage->setModal(false);
+ mySizeMessage->setStyleSheet("background-color:lightyellow;");
+ aMsgLay = new QVBoxLayout(mySizeMessage);
+ aMsg = tr("A size of Sketch view can be defined here.");
+ aMsgLay->addWidget(new QLabel(aMsg, mySizeMessage));
+ mySizeMessage->hide();
+
QString aText = translate(theData->getProperty("title"));
QLabel* aLabel = new QLabel(aText, aFirstWgt);
aLabel->setWordWrap(true);
connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
aLayout->addWidget(aPlaneBtn);
+ aLayout->addSpacing(15);
+
myDoFLabel = new QLabel("", aSecondWgt);
aLayout->addWidget(myDoFLabel);
+ myShowDOFBtn = new QPushButton(tr("Show remaining DoFs"), aSecondWgt);
+ aLayout->addWidget(myShowDOFBtn);
+ myShowDOFBtn->setEnabled(false);
+ connect(myShowDOFBtn, SIGNAL(clicked(bool)), SLOT(onShowDOF()));
+
myStackWidget->addWidget(aSecondWgt);
//setLayout(aLayout);
GeomPlanePtr aPlane = plane();
if (!aPlane.get())
return;
+
+ myPartSetMessage->hide();
+ mySizeMessage->hide();
+
// 1. hide main planes if they have been displayed and display sketch preview plane
myPreviewPlanes->erasePreviewPlanes(myWorkshop);
mySizeOfViewWidget->setVisible(false);
}
+void PartSet_WidgetSketchLabel::showEvent(QShowEvent* theEvent)
+{
+ ModuleBase_WidgetValidated::showEvent(theEvent);
+ QTimer::singleShot(10, this, SLOT(onShowPanel()));
+}
+
+void PartSet_WidgetSketchLabel::onShowPanel()
+{
+ if (mySizeOfViewWidget->isVisible()) {
+ DocumentPtr aDoc = feature()->document();
+ DocumentPtr aModDoc = ModelAPI_Session::get()->moduleDocument();
+ if (aModDoc == aDoc) {
+ myPartSetMessage->move(mapToGlobal(geometry().bottomLeft()));
+ myPartSetMessage->show();
+ }
+ QPoint aPnt = mySizeOfView->mapToGlobal(mySizeOfView->geometry().center());
+ mySizeMessage->move(aPnt);
+ mySizeMessage->show();
+ }
+}
+
void PartSet_WidgetSketchLabel::deactivate()
{
ModuleBase_WidgetValidated::deactivate();
int aDoF = aVal.toInt();
if (aDoF == 0) {
myDoFLabel->setText(tr("Sketch is fully fixed (DoF = 0)"));
+ myShowDOFBtn->setEnabled(false);
} else {
myDoFLabel->setText(tr("DoF (degrees of freedom) = ") + aVal);
+ myShowDOFBtn->setEnabled(true);
}
}
}
else {
myDoFLabel->setText("");
+ myShowDOFBtn->setEnabled(false);
}
}
return true;
}
+
+
+void PartSet_WidgetSketchLabel::onShowDOF()
+{
+ CompositeFeaturePtr aCompFeature =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+ if (aCompFeature.get()) {
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS);
+ ModelAPI_EventCreator::get()->sendUpdated(aCompFeature, anEvent);
+ Events_Loop::loop()->flush(anEvent);
+ }
+}
#include <TopoDS_Shape.hxx>
+#include <QStackedWidget>
#include <QMap>
class PartSet_PreviewPlanes;
class QCheckBox;
class QStackedWidget;
class QLineEdit;
+class QPushButton;
+class QDialog;
/**
* \ingroup Modules
/// \param thePrs a presentation
static bool canFillSketch(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
+ /// If widgets has several panels then this method has to show a page which contains information
+ /// for current feature. By default does nothing
+ virtual void showInformativePage() {
+ if (myStackWidget) myStackWidget->setCurrentIndex(1);
+ }
+
signals:
/// Signal on plane selection
void planeSelected(const std::shared_ptr<GeomAPI_Pln>& thePln);
/// \param thePrs a presentation
bool fillSketchPlaneBySelection(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
+
+ virtual void showEvent(QShowEvent* theEvent);
+
private slots:
/// A slot called on set sketch plane view
void onSetPlaneView();
void onChangePlane();
+ void onShowDOF();
+
+ void onShowPanel();
+
private:
/// Set sketch plane by shape
/// \param theShape a planar face
QStackedWidget* myStackWidget;
QLabel* myDoFLabel;
+ QPushButton* myShowDOFBtn;
bool myOpenTransaction;
bool myIsSelection;
+
+ QDialog* myPartSetMessage;
+ QDialog* mySizeMessage;
};
#endif
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>PartSet_MenuMgr</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Activate</source>
+ <translation>Activer</translation>
+ </message>
+ <message>
+ <source>Edit...</source>
+ <translation>Modifier...</translation>
+ </message>
+ <message>
+ <source>Detach</source>
+ <translation>Détacher</translation>
+ </message>
+ <message>
+ <source>Detach %1</source>
+ <translation>Détachez %1</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetPoint2D</name>
+ <message>
+ <source>X</source>
+ <translation>X</translation>
+ </message>
+ <message>
+ <source>Y</source>
+ <translation>Y</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetSketchCreator</name>
+ <message>
+ <source>Size of the view</source>
+ <translation>Taille de la vue</translation>
+ </message>
+ <message>
+ <source>Apply current feature</source>
+ <translation>Appliquer la fonctionnalité actuelle</translation>
+ </message>
+ <message>
+ <source>Sketch is invalid and will be deleted.
+Error: %1</source>
+ <translation>L'esquisse n'est pas valide et sera supprimée.
+Erreur : %1</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetSketchLabel</name>
+ <message>
+ <source>Size of the view</source>
+ <translation>Taille de la vue</translation>
+ </message>
+ <message>
+ <source>Remove external dependencies</source>
+ <translation>Supprimer les dépendances externes</translation>
+ </message>
+ <message>
+ <source>Sketcher plane</source>
+ <translation>Plan du Sketcher</translation>
+ </message>
+ <message>
+ <source>Reversed</source>
+ <translation>Renversé</translation>
+ </message>
+ <message>
+ <source>Set plane view</source>
+ <translation>Définir la vue plane</translation>
+ </message>
+ <message>
+ <source>Show geometrical constraints</source>
+ <translation>Afficher les contraintes géométriques</translation>
+ </message>
+ <message>
+ <source>Show dimensional constraints</source>
+ <translation>Afficher les contraintes dimensionnelles</translation>
+ </message>
+ <message>
+ <source>Show existing expressions</source>
+ <translation>Afficher les expressions existantes</translation>
+ </message>
+ <message>
+ <source>Show free points</source>
+ <translation>Afficher les points libres</translation>
+ </message>
+ <message>
+ <source>Automatic constraints</source>
+ <translation>Contraintes automatiques</translation>
+ </message>
+ <message>
+ <source>Automatic vertical and horizontal constraints</source>
+ <translation>Automatique des contraintes verticales et horizontales</translation>
+ </message>
+ <message>
+ <source>Change sketch plane</source>
+ <translation>Changer le plan d'esquisse</translation>
+ </message>
+ <message>
+ <source>Sketch is fully fixed (DoF = 0)</source>
+ <translation>L'esquisse est entièrement fixée (DdL = 0)</translation>
+ </message>
+ <message>
+ <source>DoF (degrees of freedom) = </source>
+ <translation>DdL (degrés de liberté) = </translation>
+ </message>
+ <message>
+ <source>Show remaining DoFs</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Parameters</source>
+ <translation>Paramètres</translation>
+ </message>
+ <message>
+ <source>Constructions</source>
+ <translation>Constructions</translation>
+ </message>
+ <message>
+ <source>Parts</source>
+ <translation>Pièces</translation>
+ </message>
+ <message>
+ <source>Results</source>
+ <translation>Résultats</translation>
+ </message>
+ <message>
+ <source>Fields</source>
+ <translation>Champs</translation>
+ </message>
+ <message>
+ <source>Groups</source>
+ <translation>Groupes</translation>
+ </message>
+</context>
+</TS>
)
SET(TEXT_RESOURCES
-# PartSetPlugin_msg_fr.ts
+ PartSetPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Part</source>
+ <translation>Pièce</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Duplicate</name>
+ <message>
+ <source>Duplicate active part</source>
+ <translation>Dupliquer la pièce active</translation>
+ </message>
+ <message>
+ <source>Duplicate part</source>
+ <translation>Dupliquer pièce</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Part</name>
+ <message>
+ <source>Create part</source>
+ <translation>Créer une pièce</translation>
+ </message>
+ <message>
+ <source>New part</source>
+ <translation>Nouvelle pièce</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Remove</name>
+ <message>
+ <source>Remove active part</source>
+ <translation>Supprimer la pièce active</translation>
+ </message>
+ <message>
+ <source>Remove part</source>
+ <translation>Supprimer une partie</translation>
+ </message>
+ </context>
+
+</TS>
)
SET(TEXT_RESOURCES
-# PrimitivesPlugin_msg_fr.ts
+ PrimitivesPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Primitives</source>
+ <translation>Primitives</translation>
+ </message>
+ <message>
+ <source>Box</source>
+ <translation>Boîte</translation>
+ </message>
+ <message>
+ <source>Cone</source>
+ <translation>Cône</translation>
+ </message>
+ <message>
+ <source>Cylinder</source>
+ <translation>Cylindre</translation>
+ </message>
+ <message>
+ <source>Sphere</source>
+ <translation>Sphère</translation>
+ </message>
+ <message>
+ <source>Torus</source>
+ <translation>Tore</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Box</name>
+ <message>
+ <source>Box</source>
+ <translation>Boîte</translation>
+ </message>
+ <message>
+ <source>Create a box</source>
+ <translation>Créer une boîte</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:CreationMethod</name>
+ <message>
+ <source>By dimensions</source>
+ <translation>Par dimensions</translation>
+ </message>
+ <message>
+ <source>By two points</source>
+ <translation>Par deux points</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:FirstPoint</name>
+ <message>
+ <source>First point</source>
+ <translation>Premier point</translation>
+ </message>
+ <message>
+ <source>Select a first point</source>
+ <translation>Sélectionnez un premier point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:FirstPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un premier point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:SecondPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un deuxième point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:SecondPoint</name>
+ <message>
+ <source>Second point</source>
+ <translation>Deuxième point</translation>
+ </message>
+ <message>
+ <source>Select a second point</source>
+ <translation>Sélectionnez un deuxième point</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:dx</name>
+ <message>
+ <source>DX</source>
+ <translation>DX</translation>
+ </message>
+ <message>
+ <source>Dimension in X</source>
+ <translation>Dimension en X</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:dy</name>
+ <message>
+ <source>DY</source>
+ <translation>DY</translation>
+ </message>
+ <message>
+ <source>Dimension in Y</source>
+ <translation>Dimension en Y</translation>
+ </message>
+ </context>
+ <context>
+ <name>Box:dz</name>
+ <message>
+ <source>DZ</source>
+ <translation>DZ</translation>
+ </message>
+ <message>
+ <source>Dimension in Z</source>
+ <translation>Dimension en Z</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Cone</name>
+ <message>
+ <source>Cone</source>
+ <translation>Cône</translation>
+ </message>
+ <message>
+ <source>Create a Cone</source>
+ <translation>Créer un cône</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:axis</name>
+ <message>
+ <source>Select the axis of the cone</source>
+ <translation>Sélectionnez l'axe du cône</translation>
+ </message>
+ <message>
+ <source>axis</source>
+ <translation>axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:base_point</name>
+ <message>
+ <source>Select the center of the base of the cone</source>
+ <translation>Sélectionnez le centre de la base du cône</translation>
+ </message>
+ <message>
+ <source>base_point</source>
+ <translation>point de base</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:base_radius</name>
+ <message>
+ <source>Base radius</source>
+ <translation>Rayon de la base</translation>
+ </message>
+ <message>
+ <source>Enter the base radius of the cone</source>
+ <translation>Entrez le rayon de base du cône</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:height</name>
+ <message>
+ <source>Enter the height of the cone</source>
+ <translation>Entrez la hauteur du cône</translation>
+ </message>
+ <message>
+ <source>height</source>
+ <translation>hauteur</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:top_radius</name>
+ <message>
+ <source>Enter the top radius of the cone</source>
+ <translation>Entrez le rayon supérieur du cône</translation>
+ </message>
+ <message>
+ <source>Top radius</source>
+ <translation>Rayon supérieur</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:base_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le centre de la base du cône.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cone:base_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Cylinder</name>
+ <message>
+ <source>Create a cylinder</source>
+ <translation>Créer un cylindre</translation>
+ </message>
+ <message>
+ <source>Cylinder</source>
+ <translation>Cylindre</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:CreationMethod</name>
+ <message>
+ <source>Cylinder</source>
+ <translation>Cylindre</translation>
+ </message>
+ <message>
+ <source>Portion of cylinder</source>
+ <translation>Portion de cylindre</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:angle</name>
+ <message>
+ <source>Enter the angle of the portion of the cylinder</source>
+ <translation>Entrez l'angle de la portion du cylindre</translation>
+ </message>
+ <message>
+ <source>angle</source>
+ <translation>angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:axis</name>
+ <message>
+ <source>Select the axis of the cylinder</source>
+ <translation>Sélectionnez l'axe du cylindre</translation>
+ </message>
+ <message>
+ <source>axis</source>
+ <translation>axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:base_point</name>
+ <message>
+ <source>Select the center of the base of the cylinder</source>
+ <translation>Sélectionnez le centre de la base du cylindre</translation>
+ </message>
+ <message>
+ <source>base_point</source>
+ <translation>point de base</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:height</name>
+ <message>
+ <source>Enter the height of the cylinder</source>
+ <translation>Entrez la hauteur du cylindre</translation>
+ </message>
+ <message>
+ <source>height</source>
+ <translation>hauteur</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:radius</name>
+ <message>
+ <source>Enter the radius of the cylinder</source>
+ <translation>Entrez le rayon du cylindre</translation>
+ </message>
+ <message>
+ <source>radius</source>
+ <translation>rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:base_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le centre de la base du cylindre.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Cylinder:base_point:GeomValidators_ConstructionComposite</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le résultat est vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Sphere</name>
+ <message>
+ <source>Create a sphere</source>
+ <translation>Créer une sphère</translation>
+ </message>
+ <message>
+ <source>Sphere</source>
+ <translation>Sphère</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sphere:center_point</name>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ <message>
+ <source>Select a center point</source>
+ <translation>Sélectionnez un point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sphere:radius</name>
+ <message>
+ <source>Enter a radius</source>
+ <translation>Entrez un rayon</translation>
+ </message>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Torus</name>
+ <message>
+ <source>Create a Torus</source>
+ <translation>Créer un tore</translation>
+ </message>
+ <message>
+ <source>Torus</source>
+ <translation>Tore</translation>
+ </message>
+ </context>
+ <context>
+ <name>Torus:axis</name>
+ <message>
+ <source>Select the axis of the torus</source>
+ <translation>Sélectionnez l'axe du tore</translation>
+ </message>
+ <message>
+ <source>axis</source>
+ <translation>axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>Torus:base_point</name>
+ <message>
+ <source>Select the center of the torus</source>
+ <translation>Sélectionnez le centre du tore</translation>
+ </message>
+ <message>
+ <source>base_point</source>
+ <translation>point de base</translation>
+ </message>
+ </context>
+ <context>
+ <name>Torus:radius</name>
+ <message>
+ <source>Enter the radius of the torus</source>
+ <translation>Entrez le rayon du tore</translation>
+ </message>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>Torus:ring_radius</name>
+ <message>
+ <source>Enter the ring radius of the torus</source>
+ <translation>Entrez le rayon de l'anneau du tore</translation>
+ </message>
+ <message>
+ <source>Ring radius</source>
+ <translation>Rayon de l'anneau</translation>
+ </message>
+ </context>
+
+</TS>
"""Package for Exchange plugin for the Parametric Geometry API of the Modeler.
"""
-from ExchangeAPI import addImport, exportToFile, exportToXAO
\ No newline at end of file
+from ExchangeAPI import addImport, exportToFile, exportToXAO
+from ExchangeAPI import exportPart, importPart
+
+from .tools import *
--- /dev/null
+# Copyright (C) 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
+#
+
+import os
+
+def removeFile(theFilename):
+ try: os.remove(theFilename)
+ except OSError: pass
+ assert not os.path.exists(theFilename), "Cannot remove file {}".format(theFilename)
)
SET(TEXT_RESOURCES
-# SHAPERGUI_msg_fr.ts
+ SHAPERGUI_msg_fr.ts
)
IF (${UPDATE_TRANSLATION})
QT5_CREATE_TRANSLATION(QM_RESOURCES
${PROJECT_FILES}
${TEXT_RESOURCES}
- OPTIONS -extensions cpp -no-recursive
+ OPTIONS -extensions cpp -no-recursive -locations none
)
ELSE(${UPDATE_TRANSLATION})
- QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ IF(${MAKE_TRANSLATION})
+ QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ ENDIF(${MAKE_TRANSLATION})
ENDIF(${UPDATE_TRANSLATION})
XGUI_Displayer* aDisp = myWorkshop->displayer();
QObjectPtrList aObjList = aDisp->displayedObjects();
+ //if (myHighlightPointAspect.IsNull()) {
+ // Handle(AIS_Trihedron) aTrihedron = mySelector->viewer()->getTrihedron();
+ // myHighlightPointAspect =
+ // new Graphic3d_AspectMarker3d(aTrihedron->getHighlightPointAspect()->Aspect().operator*());
+ //}
+ if (myOldSelectionColor.size() == 0)
+ myOldSelectionColor = aDisp->selectionColor();
+
AIS_ListOfInteractive aList;
aContext->DisplayedObjects(aList);
AIS_ListIteratorOfListOfInteractive aLIt;
}
// Delete selector because it has to be redefined on next activation
if (mySelector) {
+ //if (!myHighlightPointAspect.IsNull()) {
+ // Handle(AIS_Trihedron) aTrihedron = mySelector->viewer()->getTrihedron();
+ // aTrihedron->getHighlightPointAspect()->SetAspect(myHighlightPointAspect);
+ // myHighlightPointAspect.Nullify();
+ //}
+ myWorkshop->displayer()->setSelectionColor(myOldSelectionColor);
myProxyViewer->setSelector(0);
delete mySelector;
mySelector = 0;
aResMgr->setValue("Study", "store_positions", myIsStorePositions);
getApp()->setEditEnabled(myIsEditEnabled);
+ myOldSelectionColor.clear();
+
// Post-processing for LoadScriptId to remove created(if it was created) SALOME Object Browser
disconnect(getApp()->action(LightApp_Application::UserID+1), SIGNAL(triggered(bool)),
this, SLOT(onScriptLoaded()));
if (aBrowser)
delete aBrowser;
myWorkshop->displayer()->updateViewer();
+ myWorkshop->updateCommandStatus();
}
//******************************************************
{
if (theMgr->getType() == OCCViewer_Viewer::Type()) {
OCCViewer_Viewer* aViewer = static_cast<OCCViewer_Viewer*>(theMgr->getViewModel());
+
+ //if (myHighlightPointAspect.IsNull()) {
+ // Handle(AIS_Trihedron) aTrihedron = aViewer->getTrihedron();
+ // myHighlightPointAspect =
+ // new Graphic3d_AspectMarker3d(aTrihedron->getHighlightPointAspect()->Aspect().operator*());
+ //}
SHAPERGUI_OCCSelector* aSelector = new SHAPERGUI_OCCSelector(aViewer,
getApp()->selectionMgr());
#ifdef SALOME_PATCH_FOR_CTRL_WHEEL
aSel->setEnabled(aSel == aSelector);
}
myProxyViewer->setSelector(aSelector);
+
+ if (myOldSelectionColor.size() == 0)
+ myOldSelectionColor = myWorkshop->displayer()->selectionColor();
+
+ std::vector<int> aColor = Config_PropManager::color("Visualization", "selection_color");
+ myWorkshop->displayer()->setSelectionColor(aColor);
return aSelector;
}
return 0;
}
aProp->setValue(aValue);
+ if ((theSection == "Visualization") && (theParam == "selection_color")) {
+ std::vector<int> aColor = Config_PropManager::color("Visualization", "selection_color");
+ myWorkshop->displayer()->setSelectionColor(aColor);
+ }
+
myWorkshop->displayer()->redisplayObjects();
}
QMap<QString, QIntList> myToolbars;
QMap<QString, QIntList> myDefaultToolbars;
bool myIsToolbarsModified;
+
+ std::vector<int> myOldSelectionColor;
+ Handle(Graphic3d_AspectMarker3d) myHighlightPointAspect;
};
#endif
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>SHAPERGUI</name>
+ <message>
+ <source>Inspection</source>
+ <translation>Inspection</translation>
+ </message>
+ <message>
+ <source>Information</source>
+ <translation>Information</translation>
+ </message>
+ <message>
+ <source>Show inspection window</source>
+ <translation>Afficher la fenêtre d'inspection</translation>
+ </message>
+ <message>
+ <source>What Is</source>
+ <translation>Qu’est-ce que c’est</translation>
+ </message>
+ <message>
+ <source>Inspection tool</source>
+ <translation>Outil d'inspection</translation>
+ </message>
+ <message>
+ <source>Edit toolbars of the module</source>
+ <translation>Editer les barres d'outils du module</translation>
+ </message>
+ <message>
+ <source>Edit toolbars...</source>
+ <translation>Editer les barres d'outils...</translation>
+ </message>
+ <message>
+ <source>Viewer</source>
+ <translation>Vue</translation>
+ </message>
+ <message>
+ <source>Default selection</source>
+ <translation>Sélection par défaut</translation>
+ </message>
+ <message>
+ <source>Faces</source>
+ <translation>Faces</translation>
+ </message>
+ <message>
+ <source>Edges</source>
+ <translation>Arêtes</translation>
+ </message>
+ <message>
+ <source>Vertices</source>
+ <translation>Sommets</translation>
+ </message>
+ <message>
+ <source>Selection sensitivity</source>
+ <translation>Sensibilité de sélection</translation>
+ </message>
+ <message>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <source>Additional highlighting</source>
+ <translation>Mise en évidence supplémentaire</translation>
+ </message>
+ <message>
+ <source>In 3d mode</source>
+ <translation>En mode 3D</translation>
+ </message>
+ <message>
+ <source>In 2d mode</source>
+ <translation>En mode 2D</translation>
+ </message>
+ <message>
+ <source>Color scale</source>
+ <translation>Échelle de couleur</translation>
+ </message>
+ <message>
+ <source>X position</source>
+ <translation>Position X</translation>
+ </message>
+ <message>
+ <source>Y position</source>
+ <translation>Position Y</translation>
+ </message>
+ <message>
+ <source>Width</source>
+ <translation>Largeur</translation>
+ </message>
+ <message>
+ <source>Height</source>
+ <translation>Hauteur</translation>
+ </message>
+ <message>
+ <source>Intervals number</source>
+ <translation>Nombre d'intervalles</translation>
+ </message>
+ <message>
+ <source>Text height</source>
+ <translation>Hauteur du texte</translation>
+ </message>
+ <message>
+ <source>Text color</source>
+ <translation>Couleur du texte</translation>
+ </message>
+ <message>
+ <source>MEN_DESK_EDIT</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
+ <name>SHAPERGUI_ToolbarItemsDlg</name>
+ <message>
+ <source>Edit toolbar</source>
+ <translation>Editer la barre d'outils</translation>
+ </message>
+ <message>
+ <source>Toolbar name:</source>
+ <translation>Nom de la barre d'outils:</translation>
+ </message>
+ <message>
+ <source>Out of toolbars:</source>
+ <translation>Hors des barres d'outils:</translation>
+ </message>
+ <message>
+ <source>In the toolbar:</source>
+ <translation>Dans la barre d'outils:</translation>
+ </message>
+</context>
+<context>
+ <name>SHAPERGUI_ToolbarsDlg</name>
+ <message>
+ <source>Toolbars</source>
+ <translation>Barres d'outils</translation>
+ </message>
+ <message>
+ <source>Toolbars:</source>
+ <translation>Barres d'outils:</translation>
+ </message>
+ <message>
+ <source>Number of commands out of toolbars:</source>
+ <translation>Nombre de commandes hors des barres d'outils:</translation>
+ </message>
+ <message>
+ <source>Add...</source>
+ <translation>Ajouter...</translation>
+ </message>
+ <message>
+ <source>Add a new empty toolbar to the toolbars list</source>
+ <translation>Ajouter une nouvelle barre d'outils vide à la liste des barres d'outils</translation>
+ </message>
+ <message>
+ <source>Edit...</source>
+ <translation>Modifier...</translation>
+ </message>
+ <message>
+ <source>Edit currently selected toolbar</source>
+ <translation>Modifier la barre d'outils actuellement sélectionnée</translation>
+ </message>
+ <message>
+ <source>Delete</source>
+ <translation>Effacer</translation>
+ </message>
+ <message>
+ <source>Delete currently selected toolbar</source>
+ <translation>Supprimer la barre d'outils actuellement sélectionnée</translation>
+ </message>
+ <message>
+ <source>Reset</source>
+ <translation>Réinitialiser</translation>
+ </message>
+ <message>
+ <source>Restore default toolbars structure</source>
+ <translation>Restaurer la structure des barres d'outils par défaut</translation>
+ </message>
+ <message>
+ <source>Create toolbar</source>
+ <translation>Créer une barre d'outils</translation>
+ </message>
+ <message>
+ <source>Name of a new toolbar</source>
+ <translation>Nom d'une nouvelle barre d'outils</translation>
+ </message>
+ <message>
+ <source>A tool bar with name %1 already exists</source>
+ <translation>Une barre d'outils portant le nom %1 existe déjà</translation>
+ </message>
+ <message>
+ <source>Toolbar %1 will be deleted. Continue?</source>
+ <translation>La barre d'outils %1 sera supprimée. Continuez ?</translation>
+ </message>
+ <message>
+ <source>Delete toolbar</source>
+ <translation>Supprimer la barre d'outils</translation>
+ </message>
+ <message>
+ <source> (%1 commands)</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+</TS>
return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(x, y));
}
-static std::shared_ptr<GeomAPI_Pnt2d> pointOnEllipse(const FeaturePtr& theFeature)
+static std::shared_ptr<GeomAPI_Pnt2d> pointOnEllipse(const FeaturePtr& theFeature,
+ bool isEllipse = true)
{
+ const std::string& anAttrName = isEllipse ? SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() :
+ SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID();
AttributePoint2DPtr aMajorAxisEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
+ theFeature->attribute(anAttrName));
return aMajorAxisEnd ? aMajorAxisEnd->pnt() : std::shared_ptr<GeomAPI_Pnt2d>();
}
aMiddlePoint = middlePointOnArc(aFeature);
else if (aFeatureKind == SketchPlugin_Ellipse::ID())
aMiddlePoint = pointOnEllipse(aFeature);
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+ aMiddlePoint = pointOnEllipse(aFeature, false);
}
return aMiddlePoint;
}
SET(TEXT_RESOURCES
SketchPlugin_msg_en.ts
+ SketchPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
Test2860.py
Test2894.py
Test3019.py
+ Test3087_1.py
+ Test3087_2.py
TestArcBehavior.py
TestChangeSketchPlane1.py
TestChangeSketchPlane2.py
TestConstraintDistanceBehavior.py
TestConstraintDistanceHorizontal.py
TestConstraintDistanceVertical.py
+ TestConstraintDistanceZero.py
+ TestConstraintDistanceHorizontalZero.py
+ TestConstraintDistanceVerticalZero.py
TestConstraintEqual.py
TestConstraintEqualEllipse.py
TestConstraintFixed.py
TestProjectionIntoResult.py
TestProjectionUpdate.py
TestRectangle.py
+ TestRemainingDoF.py
TestRemoveEllipse.py
TestRemoveEllipticArc.py
TestRemoveSketch.py
TestMoveArc.py
TestMoveCircle.py
TestMoveEllipse.py
+ TestMoveEllipticArc.py
TestMoveLine.py
TestMovementComplex.py
TestMovePoint.py
#include "SketchPlugin_ConstraintAngle.h"
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Tools.h>
#include <SketcherPrs_Tools.h>
#include <ModelAPI_AttributeDouble.h>
#include <SketcherPrs_Factory.h>
#include <SketcherPrs_Tools.h>
-#include <math.h>
+#include <cmath>
+#include <regex>
+#include <sstream>
const double tolerance = 1.e-7;
#define PI 3.1415926535897932
void SketchPlugin_ConstraintAngle::initAttributes()
{
+ ModelAPI_ValidatorsFactory* aValidators = ModelAPI_Session::get()->validators();
+
data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
- data()->addAttribute(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID(),
- ModelAPI_AttributeDouble::typeId());
- data()->addAttribute(SketchPlugin_ConstraintAngle::TYPE_ID(),
- ModelAPI_AttributeInteger::typeId());
+ data()->addAttribute(ANGLE_VALUE_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(TYPE_ID(), ModelAPI_AttributeInteger::typeId());
+
+ data()->addAttribute(ANGLE_REVERSED_FIRST_LINE_ID(), ModelAPI_AttributeBoolean::typeId());
+ data()->addAttribute(ANGLE_REVERSED_SECOND_LINE_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ data()->addAttribute(LOCATION_TYPE_ID(), ModelAPI_AttributeInteger::typeId());
+ aValidators->registerNotObligatory(getKind(), LOCATION_TYPE_ID());
+
+ data()->addAttribute(SELECTED_FIRST_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->attribute(SELECTED_FIRST_POINT_ID())->setIsArgument(false);
+ aValidators->registerNotObligatory(getKind(), SELECTED_FIRST_POINT_ID());
- data()->addAttribute(SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID(),
- ModelAPI_AttributeBoolean::typeId());
- data()->addAttribute(SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID(),
- ModelAPI_AttributeBoolean::typeId());
+ data()->addAttribute(SELECTED_SECOND_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->attribute(SELECTED_SECOND_POINT_ID())->setIsArgument(false);
+ aValidators->registerNotObligatory(getKind(), SELECTED_SECOND_POINT_ID());
- data()->addAttribute(SketchPlugin_ConstraintAngle::LOCATION_TYPE_ID(),
- ModelAPI_AttributeInteger::typeId());
- ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATION_TYPE_ID());
+ if (attribute(TYPE_ID())->isInitialized())
+ myPrevAngleType = integer(TYPE_ID())->value();
+ else
+ myPrevAngleType = (int)SketcherPrs_Tools::ANGLE_DIRECT;
}
void SketchPlugin_ConstraintAngle::colorConfigInfo(std::string& theSection, std::string& theName,
{
std::shared_ptr<ModelAPI_Data> aData = data();
- std::shared_ptr<ModelAPI_AttributeRefAttr> anAttrA =
- aData->refattr(SketchPlugin_Constraint::ENTITY_A());
- std::shared_ptr<ModelAPI_AttributeRefAttr> anAttrB =
- aData->refattr(SketchPlugin_Constraint::ENTITY_B());
+ AttributeRefAttrPtr anAttrA = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr anAttrB = aData->refattr(SketchPlugin_Constraint::ENTITY_B());
if (!anAttrA->isInitialized() || !anAttrB->isInitialized())
return;
- AttributeDoublePtr anAttrValue = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- aData->attribute(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
+ AttributeDoublePtr anAttrValue = real(ANGLE_VALUE_ID());
+ if (!anAttrValue->isInitialized())
+ calculateAngle();
- if (!anAttrValue->isInitialized()) {
- double anAngle = calculateAngle();
- anAttrValue->setValue(anAngle);
- updateConstraintValueByAngleValue();
- }
// the value should to be computed here, not in the
// getAISObject in order to change the model value
// inside the object transaction. This is important for creating a constraint by preselection.
AISObjectPtr anAIS = SketcherPrs_Factory::angleConstraint(this, sketch(),
thePrevious);
+ if (anAIS.get() && !thePrevious.get())
+ SketchPlugin_Tools::setDimensionColor(anAIS);
return anAIS;
}
std::shared_ptr<ModelAPI_Data> aData = data();
if (!aData)
return;
- FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
- FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
+
+ if (theID == TYPE_ID())
+ updateAngleValue();
+
+ FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_A());
+ FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_B());
if (!aLineA || !aLineB)
return;
- if (theID == SketchPlugin_Constraint::ENTITY_A() ||
- theID == SketchPlugin_Constraint::ENTITY_B()) {
- AttributeDoublePtr aValueAttr = real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID());
- AttributeDoublePtr aConstrValueAttr = real(SketchPlugin_Constraint::VALUE());
- // only if one of attributes is not initialized, try to compute the current value
- if (!aValueAttr->isInitialized() || !aConstrValueAttr->isInitialized()) {
- if (aValueAttr->isInitialized() && !aConstrValueAttr->isInitialized())
- // initialize base value of constraint
- updateConstraintValueByAngleValue();
- double anAngle = calculateAngle();
- aValueAttr->setValue(anAngle);
- updateConstraintValueByAngleValue();
- }
- } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+ if (theID == ENTITY_A() || theID == ENTITY_B() ||
+ theID == TYPE_ID() || theID == ANGLE_VALUE_ID()) {
+ calculateAngle();
+ } else if (theID == FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
// Recalculate flyout point in local coordinates
// coordinates are calculated according to the center of shapes intersection
std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FLYOUT_VALUE_PNT()));
std::shared_ptr<ModelAPI_Data> aData = data();
std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
- FeaturePtr aLineA =
- SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
- FeaturePtr aLineB =
- SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
// Intersection of lines
std::shared_ptr<GeomAPI_Pnt2d> anInter = intersect(aLineA, aLineB);
aFlyoutAttr->setValue(aFlyoutAttr->x() + tolerance, aFlyoutAttr->y());
myFlyoutUpdate = false;
}
- else if (theID == SketchPlugin_ConstraintAngle::TYPE_ID()) {
- std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
- double anAngle = calculateAngle();
- if (aValueAttr->text().empty())
- aValueAttr->setValue(anAngle);
- else {
- aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_ConstraintAngle::VALUE()));
- aValueAttr->setValue(anAngle);
- }
- }
- else if (theID == SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()) {
- updateConstraintValueByAngleValue();
- }
}
-double SketchPlugin_ConstraintAngle::calculateAngle()
+void SketchPlugin_ConstraintAngle::calculateAngle()
{
+ // update *_REVERSED_* flags
+ calculateAnglePosition();
+
std::shared_ptr<ModelAPI_Data> aData = data();
std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
- FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
- FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
+ FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_A());
+ FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_B());
- std::shared_ptr<GeomDataAPI_Point2D> aStartA = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineA->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndA = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineA->attribute(SketchPlugin_Line::END_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aStartB = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineB->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndB = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineB->attribute(SketchPlugin_Line::END_ID()));
-
- std::shared_ptr<GeomAPI_Angle2d> anAng;
- if (!attribute(ANGLE_REVERSED_FIRST_LINE_ID())->isInitialized() ||
- !attribute(ANGLE_REVERSED_SECOND_LINE_ID())->isInitialized())
- anAng = std::shared_ptr<GeomAPI_Angle2d>(new GeomAPI_Angle2d(
- aStartA->pnt(), aEndA->pnt(), aStartB->pnt(), aEndB->pnt()));
- else {
- std::shared_ptr<GeomAPI_Lin2d> aLine1(new GeomAPI_Lin2d(aStartA->pnt(), aEndA->pnt()));
- bool isReversed1 = boolean(ANGLE_REVERSED_FIRST_LINE_ID())->value();
- std::shared_ptr<GeomAPI_Lin2d> aLine2(new GeomAPI_Lin2d(aStartB->pnt(), aEndB->pnt()));
- bool isReversed2 = boolean(ANGLE_REVERSED_SECOND_LINE_ID())->value();
- anAng = std::shared_ptr<GeomAPI_Angle2d>(
+ GeomPnt2dPtr aStartA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::START_ID());
+ GeomPnt2dPtr aEndA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::END_ID());
+ GeomPnt2dPtr aStartB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::START_ID());
+ GeomPnt2dPtr aEndB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::END_ID());
+
+ std::shared_ptr<GeomAPI_Lin2d> aLine1(new GeomAPI_Lin2d(aStartA, aEndA));
+ std::shared_ptr<GeomAPI_Lin2d> aLine2(new GeomAPI_Lin2d(aStartB, aEndB));
+
+ bool isReversed1 = boolean(ANGLE_REVERSED_FIRST_LINE_ID())->value();
+ bool isReversed2 = boolean(ANGLE_REVERSED_SECOND_LINE_ID())->value();
+
+ std::shared_ptr<GeomAPI_Angle2d> anAng(
new GeomAPI_Angle2d(aLine1, isReversed1, aLine2, isReversed2));
- }
double anAngle = anAng->angleDegree();
- std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(data()->attribute(VALUE()));
- std::shared_ptr<ModelAPI_AttributeDouble> anAngleValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(data()->attribute(ANGLE_VALUE_ID()));
- if (!aValueAttr->isInitialized())
- aValueAttr->setValue(anAngle);
- /// an angle value should be corrected by the current angle type
- anAngle = getAngleForType(anAngleValueAttr->text().empty() ?
- anAngle : anAngleValueAttr->value());
- boolean(ANGLE_REVERSED_FIRST_LINE_ID())->setValue(anAng->isReversed(0));
- boolean(ANGLE_REVERSED_SECOND_LINE_ID())->setValue(anAng->isReversed(1));
- return anAngle;
+
+ AttributeDoublePtr anAngleValueAttr = real(ANGLE_VALUE_ID());
+ if (!anAngleValueAttr->isInitialized())
+ anAngleValueAttr->setValue(getAngleForType(fabs(anAngle)));
+
+ anAngle /= fabs(anAngle);
+ anAngle *= getAngleForType(anAngleValueAttr->value());
+
+ // update value of the constraint to be passed to the solver
+ real(SketchPlugin_Constraint::VALUE())->setValue(anAngle);
}
-double SketchPlugin_ConstraintAngle::getAngleForType(double theAngle, bool isPreviousValueObtuse)
+void SketchPlugin_ConstraintAngle::calculateAnglePosition()
{
- double anAngle = theAngle;
+ if (attribute(ANGLE_REVERSED_FIRST_LINE_ID())->isInitialized() &&
+ attribute(ANGLE_REVERSED_SECOND_LINE_ID())->isInitialized())
+ return; // already calculated
- std::shared_ptr<ModelAPI_Data> aData = data();
- std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeInteger>(aData->attribute(SketchPlugin_ConstraintAngle::TYPE_ID()));
- SketcherPrs_Tools::AngleType anAngleType = (SketcherPrs_Tools::AngleType)(aTypeAttr->value());
- switch (anAngleType) {
+ DataPtr aData = data();
+ FeaturePtr aLineA = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_A());
+ FeaturePtr aLineB = SketcherPrs_Tools::getFeatureLine(aData, ENTITY_B());
+
+ GeomPnt2dPtr aStartA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::START_ID());
+ GeomPnt2dPtr aEndA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::END_ID());
+ GeomPnt2dPtr aStartB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::START_ID());
+ GeomPnt2dPtr aEndB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::END_ID());
+
+ bool isReversed1 = false;
+ bool isReversed2 = false;
+
+ GeomPnt2dPtr aSelected1 = SketcherPrs_Tools::getPoint(this, SELECTED_FIRST_POINT_ID());
+ GeomPnt2dPtr aSelected2 = SketcherPrs_Tools::getPoint(this, SELECTED_SECOND_POINT_ID());
+ if (aSelected1 && aSelected2) {
+ GeomPnt2dPtr anInterPnt = intersect(aLineA, aLineB);
+ if (!anInterPnt)
+ return;
+ std::shared_ptr<GeomAPI_XY> anInterXY = anInterPnt->xy();
+ isReversed1 = aSelected1->xy()->decreased(anInterXY)->dot(
+ aEndA->xy()->decreased(aStartA->xy())) < -tolerance;
+ isReversed2 = aSelected2->xy()->decreased(anInterXY)->dot(
+ aEndB->xy()->decreased(aStartB->xy())) < -tolerance;
+ }
+ else {
+ // no point is selected (document opened or Python script is loaded),
+ // calculate basing on the value
+ std::shared_ptr<GeomAPI_Angle2d> anAng(new GeomAPI_Angle2d(aStartA, aEndA, aStartB, aEndB));
+ isReversed1 = anAng->isReversed(0);
+ isReversed2 = anAng->isReversed(1);
+ }
+
+ // adjust reversed flags according to the angle type
+ AttributeIntegerPtr aTypeAttr = integer(TYPE_ID());
+ if (aTypeAttr && aTypeAttr->isInitialized() &&
+ (SketcherPrs_Tools::AngleType)(aTypeAttr->value()) == SketcherPrs_Tools::ANGLE_COMPLEMENTARY)
+ isReversed1 = !isReversed1;
+
+ boolean(ANGLE_REVERSED_FIRST_LINE_ID())->setValue(isReversed1);
+ boolean(ANGLE_REVERSED_SECOND_LINE_ID())->setValue(isReversed2);
+}
+
+static double angleForType(const double theAngle, const int theType)
+{
+ double anAngle = theAngle;
+ switch ((SketcherPrs_Tools::AngleType)theType) {
case SketcherPrs_Tools::ANGLE_DIRECT:
anAngle = theAngle;
- break;
- case SketcherPrs_Tools::ANGLE_COMPLEMENTARY: {
- if (theAngle > 180 || isPreviousValueObtuse)
- anAngle = theAngle - 180.0;
- else
- anAngle = 180.0 - theAngle;
-
- if (anAngle < 0.0)
- anAngle += 360.0;
- }
- break;
+ break;
+ case SketcherPrs_Tools::ANGLE_COMPLEMENTARY:
+ anAngle = 180.0 - theAngle;
+ break;
case SketcherPrs_Tools::ANGLE_BACKWARD:
anAngle = 360.0 - theAngle;
- break;
+ break;
default:
break;
}
return anAngle;
}
-void SketchPlugin_ConstraintAngle::updateConstraintValueByAngleValue()
+double SketchPlugin_ConstraintAngle::getAngleForType(double theAngle)
{
- std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID()));
- double anAngle = aValueAttr->value();
-
- /// an angle value should be corrected by the current angle type
- aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
- if (!aValueAttr->isInitialized())
- calculateAngle();
- anAngle = getAngleForType(anAngle, aValueAttr->value() > 180.0);
- aValueAttr->setValue(anAngle);
+ return angleForType(theAngle, integer(TYPE_ID())->value());
+}
+
+void SketchPlugin_ConstraintAngle::updateAngleValue()
+{
+ AttributeIntegerPtr anAngleType = integer(TYPE_ID());
+ AttributeDoublePtr anAngleValueAttr = real(ANGLE_VALUE_ID());
+ if (anAngleValueAttr->isInitialized()) {
+ if (anAngleValueAttr->text().empty()) {
+ // calculate value related to the type twice:
+ // the first time - to return to direct angle,
+ // the second time - to apply new type
+ double aValue = angleForType(anAngleValueAttr->value(), myPrevAngleType);
+ aValue = angleForType(aValue, anAngleType->value());
+ anAngleValueAttr->setValue(aValue);
+ }
+ else {
+ // process the parametric value
+ std::string anAngleText = anAngleValueAttr->text();
+ std::regex anAngleRegex("\\s*([-+]?[0-9]*\\.?[0-9]*)\\s*([-+])\\s*\\((.*)\\)",
+ std::regex_constants::ECMAScript);
+
+ double anAnglePrefix = 0.0;
+ static const char aSignPrefix[2] = { '-', '+' };
+ int aSignInd = 1;
+
+ std::smatch aResult;
+ if (std::regex_search(anAngleText, aResult, anAngleRegex)) {
+ anAnglePrefix = std::atof(aResult[1].str().c_str());
+ aSignInd = aResult[2].str()[0] == aSignPrefix[0] ? 0 : 1;
+ anAngleText = aResult[3].str();
+ }
+
+ if (myPrevAngleType != SketcherPrs_Tools::ANGLE_DIRECT)
+ aSignInd = 1 - aSignInd;
+ anAnglePrefix = angleForType(anAnglePrefix, myPrevAngleType);
+
+ if (anAngleType->value() != SketcherPrs_Tools::ANGLE_DIRECT)
+ aSignInd = 1 - aSignInd;
+ anAnglePrefix = angleForType(anAnglePrefix, anAngleType->value());
+
+ std::ostringstream aText;
+ bool isPrintSign = true;
+ if (fabs(anAnglePrefix) > tolerance)
+ aText << anAnglePrefix;
+ else
+ isPrintSign = aSignInd == 0;
+ if (isPrintSign)
+ aText << " " << aSignPrefix[aSignInd] << " (";
+ aText << anAngleText << (isPrintSign ? ")" : "");
+ anAngleValueAttr->setText(aText.str());
+ }
+ }
+ myPrevAngleType = anAngleType->value();
}
bool SketchPlugin_ConstraintAngle::compute(const std::string& theAttributeId)
return false;
// Start and end points of lines
- std::shared_ptr<GeomDataAPI_Point2D> aPointA1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineA->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aPointA2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineA->attribute(SketchPlugin_Line::END_ID()));
-
- std::shared_ptr<GeomAPI_Pnt2d> aStartA = aPointA1->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aEndA = aPointA2->pnt();
+ GeomPnt2dPtr aStartA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::START_ID());
+ GeomPnt2dPtr aEndA = SketcherPrs_Tools::getPoint(aLineA.get(), SketchPlugin_Line::END_ID());
if (aStartA->distance(aEndA) < tolerance)
return false;
- std::shared_ptr<GeomDataAPI_Point2D> aPointB1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineB->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aPointB2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aLineB->attribute(SketchPlugin_Line::END_ID()));
-
- std::shared_ptr<GeomAPI_Pnt2d> aStartB = aPointB1->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aEndB = aPointB2->pnt();
+ GeomPnt2dPtr aStartB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::START_ID());
+ GeomPnt2dPtr aEndB = SketcherPrs_Tools::getPoint(aLineB.get(), SketchPlugin_Line::END_ID());
if (aStartB->distance(aEndB) < tolerance)
return false;
std::shared_ptr<GeomAPI_Pnt2d> intersect(FeaturePtr theLine1, FeaturePtr theLine2)
{
// Start and end points of lines
- std::shared_ptr<GeomDataAPI_Point2D> aPointA1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theLine1->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aPointA2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theLine1->attribute(SketchPlugin_Line::END_ID()));
-
- std::shared_ptr<GeomDataAPI_Point2D> aPointB1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theLine2->attribute(SketchPlugin_Line::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aPointB2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theLine2->attribute(SketchPlugin_Line::END_ID()));
-
- std::shared_ptr<GeomAPI_Pnt2d> aStartA = aPointA1->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aEndA = aPointA2->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aStartB = aPointB1->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aEndB = aPointB2->pnt();
+ const std::string& aLineStartAttr = SketchPlugin_Line::START_ID();
+ const std::string& aLineEndAttr = SketchPlugin_Line::END_ID();
+ GeomPnt2dPtr aStartA = SketcherPrs_Tools::getPoint(theLine1.get(), aLineStartAttr);
+ GeomPnt2dPtr aEndA = SketcherPrs_Tools::getPoint(theLine1.get(), aLineEndAttr);
+ GeomPnt2dPtr aStartB = SketcherPrs_Tools::getPoint(theLine2.get(), aLineStartAttr);
+ GeomPnt2dPtr aEndB = SketcherPrs_Tools::getPoint(theLine2.get(), aLineEndAttr);
if (aStartA->distance(aEndA) < tolerance || aStartB->distance(aEndB) < tolerance)
std::shared_ptr<GeomAPI_Pnt2d>();
return MY_LOCATION_TYPE_ID;
}
+ /// attribute name indicating the first point selected
+ inline static const std::string& SELECTED_FIRST_POINT_ID()
+ {
+ static const std::string MY_SELECTED_FIRST_POINT_ID("SelectedPointA");
+ return MY_SELECTED_FIRST_POINT_ID;
+ }
+
+ /// attribute name indicating the second point selected
+ inline static const std::string& SELECTED_SECOND_POINT_ID()
+ {
+ static const std::string MY_SELECTED_SECOND_POINT_ID("SelectedPointB");
+ return MY_SELECTED_SECOND_POINT_ID;
+ }
/// \brief Creates a new part document if needed
SKETCHPLUGIN_EXPORT virtual void execute();
/// Returns the AIS preview
SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_ConstraintAngle();
+
+protected:
/// Calculate current value of the angle
- double calculateAngle();
+ void calculateAngle();
+
+ /// Compute the position of the angle presentation (the quarter selected by the user)
+ void calculateAnglePosition();
/// Converts the angle value according to the current angle type and sketch plane normal.
/// The in/out angle is in degree.
/// \param theAngle a source for the calculated angle
- /// \param isPreviousValueObtuse a flag if obtuse should be processed
/// \param a double angle value
- double getAngleForType(double theAngle, bool isPreviousValueObtuse = false);
+ double getAngleForType(double theAngle);
- /// Update value of VALUE attribute by the combination of the current angle type and angle value
- void updateConstraintValueByAngleValue();
-
- /// \brief Use plugin manager for features creation
- SketchPlugin_ConstraintAngle();
+ /// Update value of ANGLE_VALUE attribute according to the current type
+ void updateAngleValue();
private:
bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point
+ int myPrevAngleType;
};
#endif
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Tools.h>
#include <SketcherPrs_Tools.h>
#include <SketcherPrs_Factory.h>
#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
+#include <GeomDataAPI_Dir.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeInteger.h>
data()->addAttribute(SketchPlugin_ConstraintDistance::LOCATION_TYPE_ID(),
ModelAPI_AttributeInteger::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATION_TYPE_ID());
+
+ AttributePtr anAttr = data()->addAttribute(SketchPlugin_ConstraintDistance::DIRECTION_ID(),
+ GeomDataAPI_Dir::typeId());
+ anAttr->setIsArgument(false);
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), DIRECTION_ID());
}
void SketchPlugin_ConstraintDistance::colorConfigInfo(std::string& theSection, std::string& theName,
AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
sketch(),
thePrevious);
+ if (anAIS.get() && !thePrevious.get())
+ SketchPlugin_Tools::setDimensionColor(anAIS);
return anAIS;
}
+static std::shared_ptr<GeomAPI_Lin2d> getLine(DataPtr theData, const std::string& theAttrName)
+{
+ FeaturePtr aLineFeature = SketcherPrs_Tools::getFeatureLine(theData, theAttrName);
+ if (!aLineFeature)
+ return GeomLine2dPtr();
+
+ std::shared_ptr<GeomDataAPI_Point2D> aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::END_ID()));
+
+ return GeomLine2dPtr(new GeomAPI_Lin2d(aStart->x(), aStart->y(), aEnd->x(), aEnd->y()));
+}
+
double SketchPlugin_ConstraintDistance::calculateCurrentDistance()
{
double aDistance = -1.;
std::shared_ptr<GeomDataAPI_Point2D> aPointB =
SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
+ GeomPnt2dPtr aGeomPntA, aGeomPntB;
+ GeomLine2dPtr aLine;
if (aPointA.get() && aPointB.get()) { // both points
- aDistance = aPointA->pnt()->distance(aPointB->pnt());
+ aGeomPntA = aPointA->pnt();
+ aGeomPntB = aPointB->pnt();
} else {
- FeaturePtr aLineFeature;
- std::shared_ptr<SketchPlugin_Line> aLine;
if (!aPointA.get() && aPointB.get()) { //Line and point
- aLineFeature = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
- aLine = std::dynamic_pointer_cast<SketchPlugin_Line>(aLineFeature);
- if (aLine.get()) {
- aDistance = aLine->distanceToPoint(aPointB->pnt());
- }
+ aLine = getLine(aData, SketchPlugin_Constraint::ENTITY_A());
+ aGeomPntB = aPointB->pnt();
+ aGeomPntA = aLine ? aLine->project(aGeomPntB) : GeomPnt2dPtr();
} else if (aPointA.get() && !aPointB.get()) { // Point and line
- aLineFeature = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
- aLine = std::dynamic_pointer_cast<SketchPlugin_Line>(aLineFeature);
- if (aLine.get()) {
- aDistance = aLine->distanceToPoint(aPointA->pnt());
- }
+ aLine = getLine(aData, SketchPlugin_Constraint::ENTITY_B());
+ aGeomPntA = aPointA->pnt();
+ aGeomPntB = aLine ? aLine->project(aGeomPntA) : GeomPnt2dPtr();
}
}
+
+ if (aGeomPntA.get() && aGeomPntB.get()) {
+ aDistance = aGeomPntA->distance(aGeomPntB);
+ if (aDistance < tolerance)
+ aDistance = 0.0;
+ }
+
+ // keep the direction between arguments for processing of the zero distance
+ std::shared_ptr<GeomDataAPI_Dir> aPointPointDir =
+ std::dynamic_pointer_cast<GeomDataAPI_Dir>(attribute(DIRECTION_ID()));
+ if (aDistance > tolerance)
+ aPointPointDir->setValue(aGeomPntB->x() - aGeomPntA->x(), aGeomPntB->y() - aGeomPntA->y(), 0.0);
+ else if (aLine) {
+ GeomDir2dPtr aLineDir = aLine->direction();
+ aPointPointDir->setValue(-aLineDir->y(), aLineDir->x(), 0.0);
+ }
+
return aDistance;
}
if (!aValueAttr->isInitialized()) {
// only if it is not initialized, try to compute the current value
double aDistance = calculateCurrentDistance();
- if (aDistance > 0) { // set as value the length of updated references
+ if (aDistance >= 0) { // set as value the length of updated references
aValueAttr->setValue(aDistance);
}
}
} else
return;
- if (aEndPnt->distance(aStartPnt) < tolerance)
- return;
-
myFlyoutUpdate = true;
- std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
-
- double X = aFlyoutDir->dot(aLineDir->xy());
- double Y = -aFlyoutDir->cross(aLineDir->xy());
- aFlyoutAttr->setValue(X, Y);
+ if (aEndPnt->distance(aStartPnt) >= tolerance) {
+ std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
+ double X = aFlyoutDir->dot(aLineDir->xy());
+ double Y = -aFlyoutDir->cross(aLineDir->xy());
+ aFlyoutAttr->setValue(X, Y);
+ }
+ else
+ aFlyoutAttr->setValue(aFlyoutDir->x(), aFlyoutDir->y());
myFlyoutUpdate = false;
}
}
return MY_SIGNED;
}
+ /// \brief The direction from the first object to the second.
+ /// To change distance value from zero to non-zero correctly.
+ inline static const std::string& DIRECTION_ID()
+ {
+ static const std::string MY_DIRECTION_ID("DistanceDirection");
+ return MY_DIRECTION_ID;
+ }
+
/// attribute name of dimension location type
inline static const std::string& LOCATION_TYPE_ID()
{
// Author: Artem ZHIDKOV
#include <SketchPlugin_ConstraintDistanceAlongDir.h>
+#include <SketchPlugin_Tools.h>
#include <SketcherPrs_Tools.h>
#include <SketcherPrs_Factory.h>
AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
sketch(),
thePrevious);
+ if (anAIS.get() && !thePrevious.get())
+ SketchPlugin_Tools::setDimensionColor(anAIS);
return anAIS;
}
#include "SketchPlugin_ConstraintLength.h"
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Tools.h>
#include <GeomDataAPI_Point2D.h>
AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
sketch(), thePrevious);
+ if (anAIS.get() && !thePrevious.get())
+ SketchPlugin_Tools::setDimensionColor(anAIS);
return anAIS;
}
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Point.h>
+#include <SketchPlugin_Tools.h>
#include <SketcherPrs_Factory.h>
#include <SketcherPrs_Tools.h>
AISObjectPtr anAIS = SketcherPrs_Factory::radiusConstraint(this, sketch(),
thePrevious);
+ if (anAIS.get() && !thePrevious.get())
+ SketchPlugin_Tools::setDimensionColor(anAIS);
return anAIS;
}
anAISObject = AISObjectPtr(new GeomAPI_AISObject);
}
anAISObject->createShape(anArcShape);
+ bool isAxiliary = false;
+ AttributeBooleanPtr aAttr = boolean(AUXILIARY_ID());
+ if (aAttr.get())
+ isAxiliary = aAttr->value();
+ SketchPlugin_Tools::customizeFeaturePrs(anAISObject, isAxiliary);
return anAISObject;
}
}
// LCOV_EXCL_STOP
-double SketchPlugin_Line::distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
-{
- double aDelta = 0;
-
- std::shared_ptr<ModelAPI_Data> aData = data();
- std::shared_ptr<GeomDataAPI_Point2D> aPoint1 =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aPoint2 =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(END_ID()));
-
- GeomAPI_Lin2d aLin2d(aPoint1->x(), aPoint1->y(), aPoint2->x(), aPoint2->y());
-
- if (false/*projection*/) { // TODO: if it has not been necessary, remove this block
- std::shared_ptr<GeomAPI_Pnt2d> aResult = aLin2d.project(thePoint);
- aDelta = aResult->distance(thePoint);
- } else { // distance
- aDelta = aLin2d.distance(thePoint);
- }
-
- return aDelta;
-}
-
const std::string& SketchPlugin_Line::getKind()
{
static std::string MY_KIND = SketchPlugin_Line::ID();
/// if message has selected object
virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
- /// Return the distance between the feature and the point
- /// \param thePoint the point
- double distanceToPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
-
/// Called on change of any argument-attribute of this object
SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
anAIS.reset(new GeomAPI_AISObject());
}
anAIS->createShape(aCompound);
+ SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());
return anAIS;
}
anAIS.reset(new GeomAPI_AISObject());
}
anAIS->createShape(aCompound);
+
+ // Modify attributes
+ SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());
+
return anAIS;
}
if (!anAIS)
anAIS.reset(new GeomAPI_AISObject());
anAIS->createShape(aCompound);
+
+ // Modify attributes
+ SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());
+
return anAIS;
}
if (!anAIS)
anAIS.reset(new GeomAPI_AISObject());
anAIS->createShape(aCompound);
+ SketchPlugin_Tools::customizeFeaturePrs(anAIS, boolean(AUXILIARY_ID())->value());
return anAIS;
}
"Sketch fully constrained color",
Config_Prop::Color, SKETCH_FULLY_CONSTRAINED_COLOR);
+ Config_PropManager::registerProp("Visualization", "sketch_line_width",
+ "Sketch line width",
+ Config_Prop::IntSpin, "3");
+
// register sketcher properties
#ifdef SET_PLANES_COLOR_IN_PREFERENCES
Config_PropManager::registerProp("Visualization", "yz_plane_color", "YZ plane color",
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Tools.h>
+#include <ModelAPI_Events.h>
+
+#include <Events_Loop.h>
#include <GeomAPI_Circ.h>
#include <GeomAPI_Edge.h>
static const double tolerance = 1.e-7;
+
SketchPlugin_Projection::SketchPlugin_Projection()
: SketchPlugin_SketchEntity(),
myIsComputing(false)
setResult(aResult);
GeomShapePtr anEmptyVal;
aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), anEmptyVal);
+
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES);
+ ModelAPI_EventCreator::get()->sendUpdated(aProjection, anEvent, false);
}
}
}
std::shared_ptr<GeomAPI_Dir> aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir)));
std::shared_ptr<GeomAPI_Dir> aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir)));
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
// update position of the sketch
std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast
<GeomDataAPI_Point>(data()->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
data()->attribute(SketchPlugin_Sketch::DIRX_ID()));
aDirX->setValue(aXDir);
- std::shared_ptr<GeomAPI_Dir> aDir = aPlane->direction();
+ data()->blockSendAttributeUpdated(aWasBlocked, true);
}
}
}
* \ingroup Plugins
* \brief Feature for creation of the new part in PartSet.
*/
-class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_ICustomPrs
+class SketchPlugin_Sketch : public ModelAPI_CompositeFeature//, public GeomAPI_ICustomPrs
{
public:
/// Sketch feature kind
static std::shared_ptr<GeomAPI_Ax3> plane(SketchPlugin_Sketch* theSketch);
/// Customize presentation of the feature
- virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
- std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
- {
- bool isCustomized = false;
- // apply the color of the result to the presentation
- if (theDefaultPrs.get())
- isCustomized = theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
- // set the sketch presentation bold
- isCustomized = thePrs->setWidth(2) || isCustomized;
-
- return isCustomized;
- }
+ //virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
+ // std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
+ //{
+ // bool isCustomized = false;
+ // // apply the color of the result to the presentation
+ // if (theDefaultPrs.get())
+ // isCustomized = theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
+ // // set the sketch presentation bold
+ // isCustomized = thePrs->setWidth(2) || isCustomized;
+
+ // return isCustomized;
+ //}
private:
/// Substitute all links to external objects by newly created features.
* This is an abstract class to give
* an interface to create the entity features such as line, circle, arc and point.
*/
-class SketchPlugin_SketchEntity : public SketchPlugin_Feature, public GeomAPI_ICustomPrs
+class SketchPlugin_SketchEntity : public SketchPlugin_Feature //, public GeomAPI_ICustomPrs
{
public:
/// Reference to the construction type of the feature
}
/// Width of the auxiliary line
- inline static const double SKETCH_LINE_WIDTH_AUXILIARY()
+ inline static const int SKETCH_LINE_WIDTH_AUXILIARY()
{
return 2;
}
/// Width of the line
- inline static const double SKETCH_LINE_WIDTH()
+ inline static const int SKETCH_LINE_WIDTH()
{
- return 3;
+ return Config_PropManager::integer("Visualization", "sketch_line_width");
}
/// Style of the auxiliary line
return false;
}
+ //virtual bool isIncludeToResult() const
+ //{
+ // AttributeBooleanPtr anAttr;
+ // std::set<AttributePtr> aRefsToMe = data()->refsToMe();
+ // std::set<AttributePtr>::const_iterator aIt;
+ // for (aIt = aRefsToMe.cbegin(); aIt != aRefsToMe.cend(); ++aIt) {
+ // if ((*aIt)->id() == "ProjectedFeature") {
+ // FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>((*aIt)->owner());
+ // if (aFeature.get()) {
+ // anAttr = aFeature->data()->boolean("IncludeToResult");
+ // if (anAttr.get())
+ // return anAttr->value();
+ // }
+ // }
+ // }
+ // return true;
+ //}
+
// LCOV_EXCL_START
/// Customize presentation of the feature
- virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
- std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
- {
- /// Store previous color values of the presentation to check it after setting specific entity
- /// color. Default color is set into presentation to have not modified isCustomized state
- /// after default customize prs is completed.
- std::vector<int> aPrevColor;
- aPrevColor.resize(3);
- thePrs->getColor(aPrevColor[0], aPrevColor[1], aPrevColor[2]);
- if (theResult.get()) {
- std::string aSection, aName, aDefault;
- theResult->colorConfigInfo(aSection, aName, aDefault);
- std::vector<int> aColor;
- aColor = Config_PropManager::color(aSection, aName);
- thePrs->setColor(aColor[0], aColor[1], aColor[2]);
- }
-
- bool isCustomized = theDefaultPrs.get() != NULL &&
- theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
- int aShapeType = thePrs->getShapeType();
- // a compound is processed like the edge because the
- // arc feature uses the compound for presentable AIS
- if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/)
- return false;
-
- // set color from preferences
- std::vector<int> aColor;
- std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
- data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
- bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
- if (isConstruction) {
- aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
- }
- else if (isExternal()) {
- aColor = Config_PropManager::color("Visualization", "sketch_external_color");
- }
- else {
- aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
- }
- if (!aColor.empty()) {
- if (theResult.get() && ModelAPI_Session::get()->isOperation()) {
- AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
- aColorAttr->setSize(3);
- // Set the color attribute in order do not use default colors in the presentation object
- for (int i = 0; i < 3; i++)
- aColorAttr->setValue(i, aColor[i]);
- }
- thePrs->setColor(aColor[0], aColor[1], aColor[2]);
- for (int i = 0; i < 3 && !isCustomized; i++)
- isCustomized = aColor[i] != aPrevColor[i];
- }
-
- if (aShapeType == 6 || aShapeType == 0) { // if this is an edge or a compound
- if (isConstruction) {
- isCustomized = thePrs->setWidth(SKETCH_LINE_WIDTH_AUXILIARY()) || isCustomized;
- isCustomized = thePrs->setLineStyle(SKETCH_LINE_STYLE_AUXILIARY()) || isCustomized;
- }
- else {
- isCustomized = thePrs->setWidth(SKETCH_LINE_WIDTH()) || isCustomized;
- isCustomized = thePrs->setLineStyle(SKETCH_LINE_STYLE()) || isCustomized;
- }
- }
- else if (aShapeType == 7) { // otherwise this is a vertex
- // The width value do not have effect on the point presentation.
- // It is defined in order to extend selection area of the object.
- thePrs->setWidth(17);
- // thePrs->setPointMarker(1, 1.); // Set point as a '+' symbol
- }
- if(isCopy()) {
- double aWidth = thePrs->width();
- isCustomized = thePrs->setWidth(aWidth / 2.5) || isCustomized;
- }
-
- if (!theResult.get()) {
- double aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
- thePrs->setDeflection(aDeflection);
- }
- return isCustomized;
- }
+ //virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
+ // std::shared_ptr<GeomAPI_ICustomPrs> theDefaultPrs)
+ //{
+ // /// Store previous color values of the presentation to check it after setting specific entity
+ // /// color. Default color is set into presentation to have not modified isCustomized state
+ // /// after default customize prs is completed.
+ // std::vector<int> aPrevColor;
+ // aPrevColor.resize(3);
+ // thePrs->getColor(aPrevColor[0], aPrevColor[1], aPrevColor[2]);
+ // if (theResult.get()) {
+ // std::string aSection, aName, aDefault;
+ // theResult->colorConfigInfo(aSection, aName, aDefault);
+ // std::vector<int> aColor;
+ // aColor = Config_PropManager::color(aSection, aName);
+ // thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+ // }
+
+ // bool isCustomized = theDefaultPrs.get() != NULL &&
+ // theDefaultPrs->customisePresentation(theResult, thePrs, theDefaultPrs);
+ // int aShapeType = thePrs->getShapeType();
+ // // a compound is processed like the edge because the
+ // // arc feature uses the compound for presentable AIS
+ // if (aShapeType != 6/*an edge*/ && aShapeType != 7/*a vertex*/ && aShapeType != 0/*compound*/)
+ // return false;
+
+ // // set color from preferences
+ // std::vector<int> aColor;
+ // std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
+ // data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
+ // bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
+ // if (isConstruction) {
+ // aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
+ // }
+ // else if (isExternal()) {
+ // aColor = Config_PropManager::color("Visualization", "sketch_external_color");
+ // }
+ // else {
+ // aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
+ // }
+ // if (!aColor.empty()) {
+ // if (theResult.get() && ModelAPI_Session::get()->isOperation()) {
+ // AttributeIntArrayPtr aColorAttr =
+ // theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
+ // aColorAttr->setSize(3);
+ // // Set the color attribute in order do not use default colors in the presentation object
+ // for (int i = 0; i < 3; i++)
+ // aColorAttr->setValue(i, aColor[i]);
+ // }
+ // thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+ // for (int i = 0; i < 3 && !isCustomized; i++)
+ // isCustomized = aColor[i] != aPrevColor[i];
+ // }
+
+ // if (aShapeType == 6 || aShapeType == 0) { // if this is an edge or a compound
+ // if (isConstruction) {
+ // isCustomized = thePrs->setWidth(SKETCH_LINE_WIDTH_AUXILIARY()) || isCustomized;
+ // isCustomized = thePrs->setLineStyle(SKETCH_LINE_STYLE_AUXILIARY()) || isCustomized;
+ // }
+ // else {
+ // isCustomized = thePrs->setWidth(SKETCH_LINE_WIDTH()) || isCustomized;
+ // isCustomized = thePrs->setLineStyle(SKETCH_LINE_STYLE()) || isCustomized;
+ // }
+ // }
+ // else if (aShapeType == 7) { // otherwise this is a vertex
+ // // The width value do not have effect on the point presentation.
+ // // It is defined in order to extend selection area of the object.
+ // thePrs->setWidth(17);
+ // // thePrs->setPointMarker(1, 1.); // Set point as a '+' symbol
+ // }
+ // if(isCopy() && !isIncludeToResult()) {
+ // double aWidth = thePrs->width();
+ // isCustomized = thePrs->setWidth(aWidth / 2.5) || isCustomized;
+ // }
+
+ // if (!theResult.get()) {
+ // double aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
+ // thePrs->setDeflection(aDeflection);
+ // }
+ // return isCustomized;
+ //}
// LCOV_EXCL_STOP
protected:
return GeomPnt2dPtr(new GeomAPI_Pnt2d(X, Y));
}
+
+void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary)
+{
+ std::vector<int> aColor;
+ int aWidth = 1;
+ if (isAxiliary) {
+ thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY());
+ aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
+ aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
+ }
+ else {
+ thePrs->setLineStyle(SketchPlugin_SketchEntity::SKETCH_LINE_STYLE());
+ aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
+ aWidth = Config_PropManager::integer("Visualization", "sketch_line_width");
+ }
+ thePrs->setWidth(aWidth);
+ thePrs->setColor(aColor[0], aColor[1], aColor[2]);
+}
+
+void setDimensionColor(const AISObjectPtr& theDimPrs)
+{
+ std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
+ if (aColor.size() == 3)
+ theDimPrs->setColor(aColor[0], aColor[1], aColor[2]);
+}
+
} // namespace SketchPlugin_Tools
#include <ModelAPI_Attribute.h>
#include <ModelAPI_AttributeRefAttr.h>
#include <GeomAPI_Shape.h>
+#include <GeomAPI_AISObject.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomAlgoAPI_ShapeTools.h>
std::shared_ptr<GeomAPI_Shape>& theTangentCurve,
std::shared_ptr<GeomAPI_Pnt2d>& thePassingPoint);
-
/// Calculate global coordinates for flyout point of Length constraint
GeomPnt2dPtr flyoutPointCoordinates(const std::shared_ptr<SketchPlugin_Constraint>& theConstraint);
+
+/// Sets attributes of feature presentation
+/// \param[in] thePrs a presentation
+/// \param[in] isAxiliary is axiliary flag
+void customizeFeaturePrs(const AISObjectPtr& thePrs, bool isAxiliary);
+
+void setDimensionColor(const AISObjectPtr& theDimPrs);
+
}; // namespace SketchPlugin_Tools
namespace SketchPlugin_SegmentationTools
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Macros</source>
+ <translation>Macros</translation>
+ </message>
+ <message>
+ <source>Sketch</source>
+ <translation>Esquisse</translation>
+ </message>
+ <message>
+ <source>Sketch drawer</source>
+ <translation>Tiroir à esquisse</translation>
+ </message>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Angular copy</source>
+ <translation>Copie angulaire</translation>
+ </message>
+ <message>
+ <source>Arc</source>
+ <translation>Arc</translation>
+ </message>
+ <message>
+ <source>Circle</source>
+ <translation>Cercle</translation>
+ </message>
+ <message>
+ <source>Coincident</source>
+ <translation>Coïncident</translation>
+ </message>
+ <message>
+ <source>Collinear</source>
+ <translation>Colinéaire</translation>
+ </message>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Ellipse</source>
+ <translation>Ellipse</translation>
+ </message>
+ <message>
+ <source>Equal</source>
+ <translation>Égal</translation>
+ </message>
+ <message>
+ <source>Fixed</source>
+ <translation>Fixé</translation>
+ </message>
+ <message>
+ <source>Horizontal</source>
+ <translation>Horizontal</translation>
+ </message>
+ <message>
+ <source>Horizontal Distance</source>
+ <translation>Distance horizontale</translation>
+ </message>
+ <message>
+ <source>Length</source>
+ <translation>Longueur</translation>
+ </message>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Middle point</source>
+ <translation>Point milieu</translation>
+ </message>
+ <message>
+ <source>Mirror copy</source>
+ <translation>Copie miroir</translation>
+ </message>
+ <message>
+ <source>Parallel</source>
+ <translation>Parallèle</translation>
+ </message>
+ <message>
+ <source>Perpendicular</source>
+ <translation>Perpendiculaire</translation>
+ </message>
+ <message>
+ <source>Projection</source>
+ <translation>Projection</translation>
+ </message>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ <message>
+ <source>Rectangle</source>
+ <translation>Rectangle</translation>
+ </message>
+ <message>
+ <source>Tangent</source>
+ <translation>Tangente</translation>
+ </message>
+ <message>
+ <source>Trim</source>
+ <translation>Réduire</translation>
+ </message>
+ <message>
+ <source>Vertical</source>
+ <translation>Verticale</translation>
+ </message>
+ <message>
+ <source>Vertical Distance</source>
+ <translation>Distance verticale</translation>
+ </message>
+ </context>
+
+ <!-- Validators -->
+
+ <context>
+ <name>Sketch:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un plan pour l'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:DirX</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un plan pour l'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:External:GeomValidators_Face</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Seule la sélection d'attribut peut être utilisée pour la face d'esquisse, pas %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:External:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>L'esquisse ne peut être créée que sur une face</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:External:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>L'esquisse ne peut être créée que sur une face plane</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:External:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a cylinder.</source>
+ <translation>L'esquisse ne peut être créée que sur une face cylindrique</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:External:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not an available face.</source>
+ <translation>L'esquisse ne peut pas être créée sur la face sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un plan pour l'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:Features</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Les objets d'esquisse ne sont pas définis</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroCircle:CircleRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>La valeur du rayon est trop petite</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Un point central n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:CircleCenter</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:FirstPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:SecondPoint</name>
+ <message>
+ <source>Attribute "SecondPoint" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:ThirdPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:CircleRadius</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:CircleRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Le rayon entier n'est pas initialisé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:CircleRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>Le rayon entier doit être défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:center_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point dans la vue</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Un point central n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:center_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue</translation>
+ </message>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:first_point</name>
+ <message>
+ <source>First point</source>
+ <translation>Premier point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue</translation>
+ </message>
+ <message>
+ <source>Passed point</source>
+ <translation>Point passé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:second_point</name>
+ <message>
+ <source>Second point</source>
+ <translation>Deuxième point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:circle_radius</name>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:passed_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:third_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroCircle:third_point</name>
+ <message>
+ <source>Third point</source>
+ <translation>Troisième point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchCircle:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchCircle:circle_center</name>
+ <message>
+ <source>Center</source>
+ <translation>Centre</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchCircle:circle_radius</name>
+ <message>
+ <source>Set radius</source>
+ <translation>Définir le rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchCircle:circle_radius</name>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintHorizontal:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal</name>
+ <message>
+ <source>ModelAPI_StateInvalidArgument</source>
+ <translation>Mauvais objet sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>L'argument de contrainte ne contient pas d'élément avec un type de forme acceptable. Le type devrait être l'un des suivants : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>L'argument de contrainte ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>L'argument de contrainte fait référence à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'argument de contrainte de type %1 n'est pas pris en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintPerpendicular:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La première ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>La première ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>La deuxième ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>La deuxième ligne fait référence à un type de forme non acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La deuxième ligne ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>La deuxième ligne fait référence à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>La deuxième ligne de type %1 n'est pas prise en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>La deuxième ligne se réfère à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La deuxième ligne se réfère à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Deux lignes externes ne peuvent pas être contraintes comme perpendiculaires</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La première ligne ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme de la première ligne est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Deux lignes externes ne peuvent pas être contraintes comme perpendiculaires</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintRadius:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le cercle n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le cercle n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintFlyoutValuePnt</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>La valeur du rayon n'est pas positive</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>Le rayon est trop petit</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Le rayon entier doit être défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>Le rayon entier doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>L'argument du cercle ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme d'argument de cercle est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintVertical</name>
+ <message>
+ <source>ModelAPI_StateInvalidArgument</source>
+ <translation>Mauvais objet sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>La première ligne fait référence à un type de forme non acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La première ligne ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>La première ligne fait référence à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>La première ligne de type %1 n'est pas prise en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>La première ligne fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La première ligne se réfère à la forme vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchLine:GeomValidators_Different</name>
+ <message>
+ <source>Attributes StartPoint and EndPoint are equal.</source>
+ <translation>Le point de départ et le point final sont identiques</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point final n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:EndPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point d'arrivée dans la vue</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:StartPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point de départ dans la vue</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:StartPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point de départ n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:EndPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point final n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point final n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:EndPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point d'arrivée dans la vue</translation>
+ </message>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:StartPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point de départ dans la vue</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:LineLength</name>
+ <message>
+ <source>Length</source>
+ <translation>Longueur</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchPoint:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchPoint:PointCoordinates</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchPoint:PointCoordinates</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchPoint:PointCoordinates</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchRectangle:GeomValidators_Different</name>
+ <message>
+ <source>Attributes RectStartPoint and RectEndPoint are equal.</source>
+ <translation>Le point de départ et le point final doivent être différents</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectEndPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point final du rectangle.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectStartPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectEndPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point final du rectangle.</translation>
+ </message>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectStartPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectEndPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectStartPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchArc:ArcRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>La valeur du rayon n'est pas positive</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcTangentPoint:SketchPlugin_ArcTangentPoint</name>
+ <message>
+ <source>The attribute ArcTangentPoint should be a point</source>
+ <translation>Le point d'arc tangent n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcCenter</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcCenter</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point central n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcEndPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point d'arrivée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcPassedPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point intermédiaire</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcStartPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:GeomValidators_Different</name>
+ <message>
+ <source>Attributes ArcCenter and ArcStartPoint are equal.</source>
+ <translation>Le point central et le point final doivent être différents</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:GeomValidators_Different</name>
+ <message>
+ <source>Attributes ArcStartPoint and ArcEndPoint are equal.</source>
+ <translation>Le point de départ et le point final doivent être différents</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point final n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>Le rayon de l'arc est trop petit</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Le rayon de l'arc entier doit être défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:ArcRadius:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>Le rayon de l'arc entier doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:Model_FeatureValidator:ArcStartPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point de départ d'arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:angle</name>
+ <message>
+ <source>Set angle</source>
+ <translation>Définir l'angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:center_point</name>
+ <message>
+ <source>Center</source>
+ <translation>Centre</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:end_point</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:radius</name>
+ <message>
+ <source>Set radius</source>
+ <translation>Définir le rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:start_point</name>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchArc:radius</name>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintMirror:ConstraintMirrorList</name>
+ <message>
+ <source>Segments</source>
+ <translation>Segments</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne miroir n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne miroir n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>La ligne miroir renvoie à un type de forme non acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La ligne de miroir ne renvoie à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>La ligne miroir renvoie à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>La ligne miroir de type %1 n'est pas prise en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>La ligne miroir renvoie à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La ligne en miroir fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintMirrorList</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionner des objets</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMultiRotation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le type d'angle n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le centre de rotation n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Le nombre total d'objets pivotés n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>Le nombre total d'objets en rotation doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Le nombre total d'objets pivotés n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>Le nombre total d'objets en rotation doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationList:SketchPlugin_CopyValidator</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationList:SketchPlugin_CopyValidator</name>
+ <message>
+ <source>The object %1 is a result of copy</source>
+ <translation>L'objet %1 est le résultat d'une copie et ne peut pas être pivoté</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le centre de rotation ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme du centre de rotation est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le centre de rotation fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Le centre de rotation se réfère à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationList</name>
+ <message>
+ <source>Segments</source>
+ <translation>Segments</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMultiTranslation:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point final du vecteur de translation n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le point final du vecteur de translation n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le point final du vecteur de translation n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le point de départ du vecteur de translation n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Le nombre total d'objets traduits n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>Le nombre total d'objets traduits doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Le nombre total d'objets traduits n'est pas défini</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationObjects:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>Le nombre total d'objets traduits doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationList:SketchPlugin_CopyValidator</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationList:SketchPlugin_CopyValidator</name>
+ <message>
+ <source>The object %1 is a result of copy</source>
+ <translation>L'objet %1 est le résultat d'une copie et ne peut pas être traduit</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le point de départ de la translation ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme du point de départ de la translation est "%1", il doit correspondre à "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le point de départ du vecteur de translation n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le point de départ se réfère à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Le point de départ se réfère à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le point final de la translation ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme du point final de la translation est "%1", il doit correspondre à "%2".</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Sélectionnez un point d'arrivée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>Le point final fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>Le point final fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationList</name>
+ <message>
+ <source>Segments</source>
+ <translation>Segments</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintAngle:ConstraintFlyoutValuePnt</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Il n’est pas possible de créer un angle entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:AngleReversedLine1</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le premier objet ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le premier type de forme d'objet est "%1", il devrait correspondre à "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Il n’est pas possible de créer un angle entre deux entités externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le deuxième objet ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le deuxième type de forme d'objet est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityA:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityB:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Une coïncidence ne peut pas être créée entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Une coïncidence ne peut pas être créée entre deux objets externes</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintDistance:ConstraintFlyoutValuePnt</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>La distance doit être définie</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>La distance est trop petite</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>La valeur de distance entière doit être définie</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>La valeur de distance entière doit être positive</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>La distance ne peut pas être définie entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le premier objet ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le premier type de forme d'objet est "%1", il devrait correspondre à "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>La distance ne peut pas être définie entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>Le deuxième objet ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le deuxième type de forme d'objet est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityA:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityB:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityB:SketchPlugin_EqualAttr</name>
+ <message>
+ <source>An empty object is used.</source>
+ <translation>Un objet vide est utilisé</translation>
+ </message>
+ <message>
+ <source>The %1 feature is not supported by the Equal constraint.</source>
+ <translation>La fonctionnalité %1 n'est pas prise en charge par la contrainte Equal.</translation>
+ </message>
+ <message>
+ <source>Features with kinds %1 and %2 can not be equal.</source>
+ <translation>Les caractéristiques avec les types %1 et %2 ne peuvent pas être égales.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Une égalité ne peut pas être définie entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Une égalité ne peut pas être définie entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityA</name>
+ <message>
+ <source>Select edge</source>
+ <translation>Sélectionnez une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityB</name>
+ <message>
+ <source>Select edge</source>
+ <translation>Sélectionnez une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le premier arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le deuxième arête</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintLength:ConstraintFlyoutValuePnt</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Définir la valeur de la longueur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>La longueur est trop petite</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Définir la valeur de la longueur entière</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>La valeur de la longueur entière n'est pas positive</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La ligne ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme de ligne est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityA:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityB:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityB:SketchPlugin_MiddlePointAttr</name>
+ <message>
+ <source>Middle point constraint allows points and lines only</source>
+ <translation>Pas de point ou de ligne sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Un milieu ne peut pas être défini pour deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Un milieu ne peut pas être défini pour deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>La première ligne n'est pas sélectionnée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Une parallèle ne peut pas être définie entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La première ligne ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme de la première ligne est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA:SketchPlugin_ExternalValidator</name>
+ <message>
+ <source>Both features, attribute and attribute in parameter, are external.</source>
+ <translation>Une parallèle ne peut pas être définie entre deux objets externes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>Le type de forme doit être %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La deuxième ligne ne fait référence à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>Le type de forme de la deuxième ligne est "%1", il devrait être "%2"</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>L'attribut avec le type %1 n'est pas traité</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>L'argument de contrainte fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>L'argument de contrainte fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It does not contain element with acceptable shape type. The type should be one of the next: %1</source>
+ <translation>La contrainte fixe fait référence à un type de forme non acceptable. Le type doit être : %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>It has reference to an empty attribute</source>
+ <translation>La contrainte fixe ne renvoie à rien</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>Shape type is "%1", it should be "%2"</source>
+ <translation>La contrainte fixe fait référence à %1 mais doit être %2</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>La contrainte fixe de type %1 n'est pas prise en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The result is empty</source>
+ <translation>La contrainte fixe fait référence à un élément non existant</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The shape is empty</source>
+ <translation>La contrainte fixe fait référence à la forme vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA</name>
+ <message>
+ <source>Select point, curve or its boundary point.</source>
+ <translation>Sélectionnez un point, une courbe ou son point limite.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityA:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityB:PartSet_DifferentObjects</name>
+ <message>
+ <source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
+ <translation>Différents objets doivent être sélectionnés</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityA:SketchPlugin_TangentAttr</name>
+ <message>
+ <source>Two segments cannot be tangent</source>
+ <translation>Deux segments ne peuvent pas être tangents</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityB:SketchPlugin_TangentAttr</name>
+ <message>
+ <source>It uses an empty object</source>
+ <translation>La sélection n'est pas valide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le deuxième objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintSplit:ConstraintEntityA:SketchPlugin_SplitValidator</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Seule la sélection d'attribut peut être utilisée pour la face d'esquisse, pas %1</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchFillet:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Définir le rayon du congé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>Le rayon du congé doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not initialized.</source>
+ <translation>Définir le rayon du congé entier</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintValue:GeomValidators_Positive</name>
+ <message>
+ <source>Integer is not positive.</source>
+ <translation>Le rayon du congé entier doit être positif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ou plusieurs points pour le congé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:fillet_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ou plusieurs points pour le congé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintEntityA:SketchPlugin_FilletVertexValidator</name>
+ <message>
+ <source>Error: List of points is empty.</source>
+ <translation>La liste des points est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintEntityA:SketchPlugin_FilletVertexValidator</name>
+ <message>
+ <source>Error: one of the selected point does not have coincidence.</source>
+ <translation>Un des points sélectionné n'a pas de coïncidence</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintEntityA:SketchPlugin_FilletVertexValidator</name>
+ <message>
+ <source>Error: One of the selected points does not have two suitable edges for fillet.</source>
+ <translation>Un des points sélectionnés ne possède pas deux arêtes appropriées pour le congé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintEntityA:SketchPlugin_FilletVertexValidator</name>
+ <message>
+ <source>Error: Edges in selected point has tangent constraint.</source>
+ <translation>Les arêtes du point sélectionné ont une contrainte de tangence</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:ConstraintEntityA:SketchPlugin_FilletVertexValidator</name>
+ <message>
+ <source>Error: Edges in selected point has tangent constraint.</source>
+ <translation>Les arêtes du point sélectionné ont une contrainte de tangence</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchProjection:ExternalFeature:SketchPlugin_ProjectionValidator</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Un argument de type %1 de la fonctionnalité de projection n'est pas pris en charge</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:ExternalFeature:SketchPlugin_ProjectionValidator</name>
+ <message>
+ <source>The attribute %1 should be an edge</source>
+ <translation>L'attribut %1 doit être une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:ExternalFeature:SketchPlugin_ProjectionValidator</name>
+ <message>
+ <source>There is no sketch referring to the current feature</source>
+ <translation>La fonction de projection n'a pas d'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:ExternalFeature</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>Sketch</name>
+ <message>
+ <source>Create sketch</source>
+ <translation>Créer une esquisse</translation>
+ </message>
+ <message>
+ <source>Sketch</source>
+ <translation>Esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:External</name>
+ <message>
+ <source>Select a plane on which to create a sketch</source>
+ <translation>Sélectionnez un plan sur lequel créer une esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:SketchPlugin_SolverErrorValidator</name>
+ <message>
+ <source>The constraint is conflicting with others. To fix this, you can either undo your operation or remove a conflicting constraint.</source>
+ <translation>La contrainte est en conflit avec les autres. Pour résoudre ce problème, vous pouvez annuler votre opération ou supprimer une contrainte en conflit.</translation>
+ </message>
+ </context>
+ <context>
+ <name>Sketch:SketchPlugin_SolverErrorValidator</name>
+ <message>
+ <source>The set of constraints lead to degenerated geometry. To fix this, you can either undo your operation or remove a constraint or the degenerated geometry.</source>
+ <translation>L'ensemble des contraintes conduit à une géométrie dégénérée. Pour résoudre ce problème, vous pouvez annuler votre opération ou supprimer une contrainte ou la géométrie dégénérée..</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintAngle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Set fixed angle between two line segments</source>
+ <translation>Définir un angle fixe entre deux segments</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:AngleType</name>
+ <message>
+ <source>Additional</source>
+ <translation>Additionnel</translation>
+ </message>
+ <message>
+ <source>Angle type</source>
+ <translation>Type d'angle</translation>
+ </message>
+ <message>
+ <source>Complementary</source>
+ <translation>Complémentaire</translation>
+ </message>
+ <message>
+ <source>Direct</source>
+ <translation>Direct</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:AngleValue</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>Valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityA</name>
+ <message>
+ <source>Line 1</source>
+ <translation>Ligne 1</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:ConstraintEntityB</name>
+ <message>
+ <source>Line 2</source>
+ <translation>Ligne 2</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:LocationType</name>
+ <message>
+ <source>Automatic</source>
+ <translation>Automatique</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>Gauche</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>Droite</translation>
+ </message>
+ <message>
+ <source>Text location</source>
+ <translation>Localisation du texte</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintAngle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Le premier objet n'est pas sélectionné</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintCoincidence</name>
+ <message>
+ <source>Coincident</source>
+ <translation>Coïncident</translation>
+ </message>
+ <message>
+ <source>Create constraint for the coincidence of two points or point on line or circle</source>
+ <translation>Créer une contrainte pour la coïncidence de deux points ou d'un point sur une ligne ou un cercle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityA</name>
+ <message>
+ <source>First object</source>
+ <translation>Premier objet</translation>
+ </message>
+ <message>
+ <source>Select a first object</source>
+ <translation>Sélectionnez un premier objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCoincidence:ConstraintEntityB</name>
+ <message>
+ <source>Second object</source>
+ <translation>Deuxième objet</translation>
+ </message>
+ <message>
+ <source>Select a second object</source>
+ <translation>Sélectionnez un deuxième objet</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintCollinear</name>
+ <message>
+ <source>Collinear</source>
+ <translation>Colinéaire</translation>
+ </message>
+ <message>
+ <source>Create constraint defining collinearity of two lines</source>
+ <translation>Créer une contrainte définissant la colinéarité de deux lignes</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:ConstraintEntityA</name>
+ <message>
+ <source>First line</source>
+ <translation>Première ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:ConstraintEntityB</name>
+ <message>
+ <source>Second line</source>
+ <translation>Deuxième ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le premier ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintCollinear:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le deuxième ligne</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintDistance</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Set fixed distance from a point to an object</source>
+ <translation>Définir une distance fixe entre un point et un objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance</name>
+ <message>
+ <source>Select objects for distance definition. Following objects can be accepted: point, line or arc end point, center of circle or arc.</source>
+ <translation>Sélectionnez des objets pour la définition de la distance. Les objets suivants peuvent être acceptés : point, ligne ou arc point final, centre du cercle ou arc.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityA</name>
+ <message>
+ <source>First object</source>
+ <translation>Premier objet</translation>
+ </message>
+ <message>
+ <source>Select point, line end point, line, center of circle or arc.</source>
+ <translation>Sélectionner un point, une fin de ligne, une ligne, le centre du cercle ou un arc.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintEntityB</name>
+ <message>
+ <source>Second object</source>
+ <translation>Deuxième objet</translation>
+ </message>
+ <message>
+ <source>Select point, line end point, line, center of circle or arc.</source>
+ <translation>Sélectionner un point, une fin de ligne, une ligne, le centre du cercle ou un arc.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:ConstraintValue</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>Valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:LocationType</name>
+ <message>
+ <source>Automatic</source>
+ <translation>Automatique</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>Gauche</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>Droite</translation>
+ </message>
+ <message>
+ <source>Text location</source>
+ <translation>Localisation du texte</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistance:SignedDistance</name>
+ <message>
+ <source>Keep distance orientation</source>
+ <translation>Garder l'orientation de la distance</translation>
+ </message>
+ <message>
+ <source>Keep orientation</source>
+ <translation>Gardez l'orientation</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintDistanceHorizontal</name>
+ <message>
+ <source>Horizontal Distance</source>
+ <translation>Distance horizontale</translation>
+ </message>
+ <message>
+ <source>Set horizontal distance between two points</source>
+ <translation>Définir la distance horizontale entre deux points</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintEntityA</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal</name>
+ <message>
+ <source>Select points for distance definition.</source>
+ <translation>Sélectionner des points pour la définition de la distance.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintEntityA</name>
+ <message>
+ <source>First point</source>
+ <translation>Premier point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintEntityB</name>
+ <message>
+ <source>Second point</source>
+ <translation>Deuxième point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintEntityB</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:DistanceValue</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>Valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:DistanceValue:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Double n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:DistanceValue:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>La valeur est trop petite</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:LocationType</name>
+ <message>
+ <source>Automatic</source>
+ <translation>Automatique</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>Gauche</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>Droite</translation>
+ </message>
+ <message>
+ <source>Text location</source>
+ <translation>Localisation du texte</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceHorizontal:ConstraintFlyoutValuePnt</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintDistanceVertical</name>
+ <message>
+ <source>Set vertical distance between two points</source>
+ <translation>Définir la distance verticale entre deux points</translation>
+ </message>
+ <message>
+ <source>Vertical Distance</source>
+ <translation>Distance verticale</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical</name>
+ <message>
+ <source>Select points for distance definition.</source>
+ <translation>Sélectionner des points pour la définition de la distance.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:ConstraintEntityA</name>
+ <message>
+ <source>First point</source>
+ <translation>Premier point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:ConstraintEntityA:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:ConstraintEntityB</name>
+ <message>
+ <source>Second point</source>
+ <translation>Deuxième point</translation>
+ </message>
+ <message>
+ <source>Select point.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:ConstraintEntityB:GeomValidators_ShapeType</name>
+ <message>
+ <source>The object is empty</source>
+ <translation>L'objet est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:DistanceValue</name>
+ <message>
+ <source>Distance</source>
+ <translation>Distance</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>Valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:DistanceValue:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Double n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:LocationType</name>
+ <message>
+ <source>Automatic</source>
+ <translation>Automatique</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>Gauche</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>Droite</translation>
+ </message>
+ <message>
+ <source>Text location</source>
+ <translation>Localisation du texte</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:ConstraintFlyoutValuePnt</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintDistanceVertical:DistanceValue:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>La valeur est trop petite.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintEqual</name>
+ <message>
+ <source>Create constraint defining equal lengths of two lines or line and arc or equal radiuses of two arcs or two circles or arc and circle</source>
+ <translation>Créer une contrainte définissant des longueurs égales de deux lignes, ou une ligne et un arc, ou des rayons égaux de deux arcs ou de deux cercles ou d'un arc et d'un cercle</translation>
+ </message>
+ <message>
+ <source>Equal</source>
+ <translation>Égal</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityA</name>
+ <message>
+ <source>First object</source>
+ <translation>Premier objet</translation>
+ </message>
+ <message>
+ <source>Select line, circle or arc</source>
+ <translation>Sélectionnez une ligne, un cercle ou un arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintEqual:ConstraintEntityB</name>
+ <message>
+ <source>Second object</source>
+ <translation>Deuxième objet</translation>
+ </message>
+ <message>
+ <source>Select line, circle or arc</source>
+ <translation>Sélectionnez une ligne, un cercle ou un arc</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintHorizontal</name>
+ <message>
+ <source>Create constraint defining horizontal line</source>
+ <translation>Créer une contrainte définissant une ligne horizontale</translation>
+ </message>
+ <message>
+ <source>Horizontal</source>
+ <translation>Horizontal</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintHorizontal:ConstraintEntityA</name>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintLength</name>
+ <message>
+ <source>Length</source>
+ <translation>Longueur</translation>
+ </message>
+ <message>
+ <source>Set fixed length of a line segment</source>
+ <translation>Définir la longueur fixe d'un segment</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength</name>
+ <message>
+ <source>Select a line on which to calculate length</source>
+ <translation>Sélectionnez une ligne sur laquelle calculer la longueur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintEntityA</name>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:ConstraintValue</name>
+ <message>
+ <source>Length</source>
+ <translation>Longueur</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>Valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintLength:LocationType</name>
+ <message>
+ <source>Automatic</source>
+ <translation>Automatique</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>Gauche</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>Droite</translation>
+ </message>
+ <message>
+ <source>Text location</source>
+ <translation>Localisation du texte</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintMiddle</name>
+ <message>
+ <source>Create constraint for setting middle point on a line</source>
+ <translation>Créer une contrainte pour définir le milieu de la ligne</translation>
+ </message>
+ <message>
+ <source>Middle point</source>
+ <translation>Point milieu</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityA</name>
+ <message>
+ <source>First object</source>
+ <translation>Premier objet</translation>
+ </message>
+ <message>
+ <source>Select a first object</source>
+ <translation>Sélectionnez un premier objet</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMiddle:ConstraintEntityB</name>
+ <message>
+ <source>Second object</source>
+ <translation>Deuxième objet</translation>
+ </message>
+ <message>
+ <source>Select a second object</source>
+ <translation>Sélectionnez un deuxième objet</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintMirror</name>
+ <message>
+ <source>Create constraint, mirroring group of objects</source>
+ <translation>Créer une contrainte, mettre en miroir un groupe d'objets</translation>
+ </message>
+ <message>
+ <source>Mirror copy</source>
+ <translation>Copie miroir</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintEntityA</name>
+ <message>
+ <source>Mirror line</source>
+ <translation>Ligne miroir</translation>
+ </message>
+ <message>
+ <source>Select mirror line</source>
+ <translation>Sélectionnez la ligne miroir</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintMirror:ConstraintMirrorList</name>
+ <message>
+ <source>Select list of objects to be mirrored</source>
+ <translation>Sélectionner la liste des objets à mettre en miroir</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintParallel</name>
+ <message>
+ <source>Create constraint defining two parallel lines</source>
+ <translation>Créer une contrainte définissant deux lignes parallèles</translation>
+ </message>
+ <message>
+ <source>Parallel</source>
+ <translation>Parallèle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityA</name>
+ <message>
+ <source>First line</source>
+ <translation>Première ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintParallel:ConstraintEntityB</name>
+ <message>
+ <source>Second line</source>
+ <translation>Deuxième ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintPerpendicular</name>
+ <message>
+ <source>Create constraint defining two orthogonal objects</source>
+ <translation>Créer une contrainte définissant deux objets orthogonaux</translation>
+ </message>
+ <message>
+ <source>Perpendicular</source>
+ <translation>Perpendiculaire</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityA</name>
+ <message>
+ <source>First object</source>
+ <translation>Premier objet</translation>
+ </message>
+ <message>
+ <source>Select line or arc</source>
+ <translation>Sélectionnez une ligne ou un arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintPerpendicular:ConstraintEntityB</name>
+ <message>
+ <source>Second object</source>
+ <translation>Deuxième objet</translation>
+ </message>
+ <message>
+ <source>Select line or arc</source>
+ <translation>Sélectionnez une ligne ou un arc</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintRadius</name>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ <message>
+ <source>Set fixed radius of a circle or an arc</source>
+ <translation>Définir le rayon fixe d'un cercle ou d'un arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius</name>
+ <message>
+ <source>Select a circle or an arc on which to calculate radius</source>
+ <translation>Sélectionnez un cercle ou un arc sur lequel calculer le rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintEntityA</name>
+ <message>
+ <source>Circle or Arc</source>
+ <translation>Cercle ou arc</translation>
+ </message>
+ <message>
+ <source>Select a circle or an arc</source>
+ <translation>Sélectionnez un cercle ou un arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:ConstraintValue</name>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ <message>
+ <source>Value</source>
+ <translation>Valeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRadius:LocationType</name>
+ <message>
+ <source>Automatic</source>
+ <translation>Automatique</translation>
+ </message>
+ <message>
+ <source>Left</source>
+ <translation>Gauche</translation>
+ </message>
+ <message>
+ <source>Right</source>
+ <translation>Droite</translation>
+ </message>
+ <message>
+ <source>Text location</source>
+ <translation>Localisation du texte</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintRigid</name>
+ <message>
+ <source>Fix an object</source>
+ <translation>Maintenir un objet</translation>
+ </message>
+ <message>
+ <source>Fixed</source>
+ <translation>Fixé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintRigid:ConstraintEntityA</name>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Select point, line end point, line, center of circle or arc.</source>
+ <translation>Sélectionner un point, une fin de ligne, une ligne, le centre du cercle ou un arc.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintTangent</name>
+ <message>
+ <source>Create constraint defining tangency of two segments with common coincident point</source>
+ <translation>Créer une contrainte définissant la tangence de deux segments avec un point de coïncidence commun</translation>
+ </message>
+ <message>
+ <source>Tangent</source>
+ <translation>Tangente</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityA</name>
+ <message>
+ <source>First object</source>
+ <translation>Premier objet</translation>
+ </message>
+ <message>
+ <source>Select line or arc</source>
+ <translation>Sélectionnez une ligne ou un arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityB</name>
+ <message>
+ <source>Second object</source>
+ <translation>Deuxième objet</translation>
+ </message>
+ <message>
+ <source>Select line or arc</source>
+ <translation>Sélectionnez une ligne ou un arc</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchConstraintVertical</name>
+ <message>
+ <source>Create constraint defining vertical line</source>
+ <translation>Créer une contrainte définissant une ligne verticale</translation>
+ </message>
+ <message>
+ <source>Vertical</source>
+ <translation>Verticale</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintVertical:ConstraintEntityA</name>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ <message>
+ <source>Select a line</source>
+ <translation>Sélectionnez une ligne</translation>
+ </message>
+ </context>
+
+ <!-- SketchDrawer -->
+ <context>
+ <name>SketchDrawer</name>
+ <message>
+ <source>Creates sketch using elements of selected shape belonging to selected plane</source>
+ <translation>Crée une esquisse en utilisant des éléments de la forme sélectionnée appartenant au plan sélectionné</translation>
+ </message>
+ <message>
+ <source>Sketch drawer</source>
+ <translation>Tiroir à esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchDrawer:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchDrawer:add_dimensions</name>
+ <message>
+ <source>Create dimensions</source>
+ <translation>Créer des dimensions</translation>
+ </message>
+ <message>
+ <source>To add dimensions into created sketch</source>
+ <translation>Pour ajouter des cotes à l'esquisse créée</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchDrawer:base_shape</name>
+ <message>
+ <source>Select a shape for extraction to sketch.</source>
+ <translation>Sélectionnez une forme à extraire pour l'esquisse.</translation>
+ </message>
+ <message>
+ <source>Shape:</source>
+ <translation>Forme:</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchDrawer:plane</name>
+ <message>
+ <source>Plane:</source>
+ <translation>Plan:</translation>
+ </message>
+ <message>
+ <source>Select plane for sketch</source>
+ <translation>Sélectionner un plan pour l'esquisse</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchFillet</name>
+ <message>
+ <source>Create constraint defining fillet between two connected segments</source>
+ <translation>Créer une contrainte définissant un congé entre deux segments connectés</translation>
+ </message>
+ <message>
+ <source>Fillet</source>
+ <translation>Congé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un ou plusieurs points pour le congé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:fillet_point</name>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Select point for fillet (should be shared by two entities only)</source>
+ <translation>Sélectionnez un point pour le congé (doit être partagé par deux entités uniquement)</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchFillet:fillet_point:SketchPlugin_FilletVertexValidator</name>
+ <message>
+ <source>Error: Bad point selected.</source>
+ <translation>Erreur : mauvais point sélectionné.</translation>
+ </message>
+ <message>
+ <source>Error: Edges in selected point has tangent constraint.</source>
+ <translation>Erreur : les arêtes du point sélectionné ont une contrainte de tangence.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchIntersectionPoint</name>
+ <message>
+ <source>Intersect edge with sketch plane</source>
+ <translation>Intersecter un bord avec un plan d'esquisse</translation>
+ </message>
+ <message>
+ <source>Intersection</source>
+ <translation>Section</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchIntersectionPoint:ExternalFeature</name>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Select external edge.</source>
+ <translation>Sélectionnez le bord externe.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchIntersectionPoint:ExternalFeature:SketchPlugin_IntersectionValidator</name>
+ <message>
+ <source>The attribute %1 should be an edge</source>
+ <translation>L'attribut %1 doit être une arête</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchIntersectionPoint:IncludeToResult</name>
+ <message>
+ <source>Include into the sketch result</source>
+ <translation>Inclure dans le résultat de l'esquisse</translation>
+ </message>
+ <message>
+ <source>Include projected feature into the sketch result</source>
+ <translation>Inclure la fonctionnalité projetée dans le résultat de l'esquisse</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchIntersectionPoint:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchIntersectionPoint:ExternalFeature</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le bord externe.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchLine</name>
+ <message>
+ <source>Create line</source>
+ <translation>Créer une ligne</translation>
+ </message>
+ <message>
+ <source>Line</source>
+ <translation>Ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchLine:LineLength</name>
+ <message>
+ <source>Length:</source>
+ <translation>Longueur:</translation>
+ </message>
+ <message>
+ <source>Line length</source>
+ <translation>Longueur de la ligne</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroArc</name>
+ <message>
+ <source>Arc</source>
+ <translation>Arc</translation>
+ </message>
+ <message>
+ <source>Create arc</source>
+ <translation>Créer un arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:center_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:arc_type</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:angle</name>
+ <message>
+ <source>Set angle</source>
+ <translation>Définir l'angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:arc_type</name>
+ <message>
+ <source>Center and two points</source>
+ <translation>Centre et deux points</translation>
+ </message>
+ <message>
+ <source>Perpendicular to line</source>
+ <translation>Perpendiculaire à la ligne</translation>
+ </message>
+ <message>
+ <source>Tangent with edge</source>
+ <translation>Tangente avec bord</translation>
+ </message>
+ <message>
+ <source>Three points on arc</source>
+ <translation>Trois points sur l'arc</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:passed_point:SketchPlugin_ThirdPointValidator</name>
+ <message>
+ <source>Selected points are on the same line</source>
+ <translation>Les points sélectionnés sont sur la même ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:radius</name>
+ <message>
+ <source>Set radius</source>
+ <translation>Définir le rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:tangent_point</name>
+ <message>
+ <source>Select point on line</source>
+ <translation>Sélectionnez un point sur la ligne</translation>
+ </message>
+ <message>
+ <source>Tangent point</source>
+ <translation>Point tangent</translation>
+ </message>
+ <message>
+ <source>Point on the perpendicular line</source>
+ <translation>Point sur la perpendiculaire</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:tangent_point:SketchPlugin_ArcTangentPoint</name>
+ <message>
+ <source>The attribute %1 should be a point</source>
+ <translation>L'attribut %1 doit être un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:tangent_point:SketchPlugin_ArcTransversalPoint</name>
+ <message>
+ <source>The attribute %1 should be a point</source>
+ <translation>L'attribut %1 doit être un point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:tangent_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:center_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point central.</translation>
+ </message>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_1</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point d'arrivée dans la vue.</translation>
+ </message>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_1</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point d'arrivée dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_2</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_3</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:passed_point</name>
+ <message>
+ <source>Passed point</source>
+ <translation>Point passé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:passed_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_1</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point de départ.</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_2</name>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:angle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_2</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:radius</name>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_1</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_2</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:tangent_point:SketchPlugin_ArcTransversalPoint</name>
+ <message>
+ <source>Unable to build perpendicular arc on %1</source>
+ <translation>Impossible de créer un arc perpendiculaire sur %1</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_2</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_3</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_2</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point dans la vue.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroCircle</name>
+ <message>
+ <source>Circle</source>
+ <translation>Cercle</translation>
+ </message>
+ <message>
+ <source>Create circle</source>
+ <translation>Créer un cercle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Un point central n'est pas sélectionné</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:circle_radius</name>
+ <message>
+ <source>Set radius</source>
+ <translation>Définir le rayon</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:circle_radius:GeomValidators_Positive</name>
+ <message>
+ <source>Value is too small.</source>
+ <translation>La valeur est trop petite.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:circle_type</name>
+ <message>
+ <source>Center and passed points</source>
+ <translation>Points centrés et passés</translation>
+ </message>
+ <message>
+ <source>Three points</source>
+ <translation>Trois points</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:third_point:SketchPlugin_ThirdPointValidator</name>
+ <message>
+ <source>Selected points are on the same line</source>
+ <translation>Les points sélectionnés sont sur la même ligne</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:first_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:second_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:third_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:circle_type</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:second_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le deuxième point.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroEllipse</name>
+ <message>
+ <source>Create ellipse</source>
+ <translation>Créer une ellipse</translation>
+ </message>
+ <message>
+ <source>Ellipse</source>
+ <translation>Ellipse</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:ellipse_type</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:passed_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:ellipse_type</name>
+ <message>
+ <source>Center, major semi-axis and passing point</source>
+ <translation>Centre, grand demi-axe et point de passage</translation>
+ </message>
+ <message>
+ <source>Major axis and passing point</source>
+ <translation>Grand axe et point de passage</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:first_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un premier point dans la vue.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:major_radius</name>
+ <message>
+ <source>Set major radius</source>
+ <translation>Définir le rayon majeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:major_radius:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Double n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:minor_radius</name>
+ <message>
+ <source>Set minor radius</source>
+ <translation>Définir le rayon mineur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:minor_radius:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Double n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:first_point</name>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ <message>
+ <source>Major axis start point</source>
+ <translation>Point de départ du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point passé.</translation>
+ </message>
+ <message>
+ <source>Passed point</source>
+ <translation>Point passé</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:second_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un deuxième point.</translation>
+ </message>
+ <message>
+ <source>Major axis end point</source>
+ <translation>Point final du grand axe</translation>
+ </message>
+ <message>
+ <source>Major axis point</source>
+ <translation>Point du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:second_point</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchEllipse:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_center</name>
+ <message>
+ <source>Center</source>
+ <translation>Centre</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_first_focus</name>
+ <message>
+ <source>First focus</source>
+ <translation>Premier foyer</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_major_axis_end_point</name>
+ <message>
+ <source>Major axis end</source>
+ <translation>Fin du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_major_axis_start_point</name>
+ <message>
+ <source>Major axis start</source>
+ <translation>Début du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_major_radius</name>
+ <message>
+ <source>Set major radius</source>
+ <translation>Définir le rayon majeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_minor_axis_end_point</name>
+ <message>
+ <source>Minor axis end</source>
+ <translation>Fin du petit axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_minor_axis_start_point</name>
+ <message>
+ <source>Minor axis start</source>
+ <translation>Début du petit axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_minor_radius</name>
+ <message>
+ <source>Set minor radius</source>
+ <translation>Définir le rayon mineur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_second_focus</name>
+ <message>
+ <source>Second focus</source>
+ <translation>Deuxième objectif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_major_radius</name>
+ <message>
+ <source>Major radius</source>
+ <translation>Rayon majeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipse:ellipse_minor_radius</name>
+ <message>
+ <source>Minor radius</source>
+ <translation>Rayon mineur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:major_radius</name>
+ <message>
+ <source>Major radius</source>
+ <translation>Rayon majeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:minor_radius</name>
+ <message>
+ <source>Minor radius</source>
+ <translation>Rayon mineur</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchEllipticArc:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_center</name>
+ <message>
+ <source>Center</source>
+ <translation>Centre</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_first_focus</name>
+ <message>
+ <source>First focus</source>
+ <translation>Premier foyer</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_major_axis_end_point</name>
+ <message>
+ <source>Major axis end</source>
+ <translation>Fin du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_major_axis_start_point</name>
+ <message>
+ <source>Major axis start</source>
+ <translation>Début du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_major_radius</name>
+ <message>
+ <source>Major radius</source>
+ <translation>Rayon majeur</translation>
+ </message>
+ <message>
+ <source>Set major radius</source>
+ <translation>Définir le rayon majeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_minor_axis_end_point</name>
+ <message>
+ <source>Minor axis end</source>
+ <translation>Fin du petit axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_minor_axis_start_point</name>
+ <message>
+ <source>Minor axis start</source>
+ <translation>Début du petit axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_minor_radius</name>
+ <message>
+ <source>Minor radius</source>
+ <translation>Rayon mineur</translation>
+ </message>
+ <message>
+ <source>Set minor radius</source>
+ <translation>Définir le rayon mineur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:ellipse_second_focus</name>
+ <message>
+ <source>Second focus</source>
+ <translation>Deuxième objectif</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:end_point</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchEllipticArc:start_point</name>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc</name>
+ <message>
+ <source>Create elliptic arc</source>
+ <translation>Créer un arc elliptique</translation>
+ </message>
+ <message>
+ <source>Elliptic arc</source>
+ <translation>Arc elliptique</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:center</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point central.</translation>
+ </message>
+ <message>
+ <source>Center point</source>
+ <translation>Point central</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:end_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point d'arrivée.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point d'arrivée.</translation>
+ </message>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:major_axis_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Sélectionnez un point d'axe majeur.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un point d'axe majeur.</translation>
+ </message>
+ <message>
+ <source>Major axis point</source>
+ <translation>Point du grand axe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:major_radius</name>
+ <message>
+ <source>Major radius</source>
+ <translation>Rayon majeur</translation>
+ </message>
+ <message>
+ <source>Set major radius</source>
+ <translation>Définir le rayon majeur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:major_radius:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Double n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:minor_radius</name>
+ <message>
+ <source>Minor radius</source>
+ <translation>Rayon mineur</translation>
+ </message>
+ <message>
+ <source>Set minor radius</source>
+ <translation>Définir le rayon mineur</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:minor_radius:GeomValidators_Positive</name>
+ <message>
+ <source>Double is not initialized.</source>
+ <translation>Double n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:start_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>L'attribut "%1" est verrouillé par la valeur de modification dans la vue.</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ </context>
+ <context>
+ <name>workshop</name>
+ <message>
+ <source>Elliptic arc</source>
+ <translation>Arc elliptique</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMultiRotation</name>
+ <message>
+ <source>Angular copy</source>
+ <translation>Copie angulaire</translation>
+ </message>
+ <message>
+ <source>Copy objects and rotate</source>
+ <translation>Copier des objets et faire pivoter</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:AngleType</name>
+ <message>
+ <source>Full angle</source>
+ <translation>Angle complet</translation>
+ </message>
+ <message>
+ <source>Single angle</source>
+ <translation>Angle unique</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationAngle</name>
+ <message>
+ <source>Angle</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>Rotation angle</source>
+ <translation>Angle de rotation</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationCenter</name>
+ <message>
+ <source>Center of rotation</source>
+ <translation>Centre de rotation</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationList</name>
+ <message>
+ <source>Segments:</source>
+ <translation>Segments:</translation>
+ </message>
+ <message>
+ <source>Select list of objects to be rotated</source>
+ <translation>Sélectionnez la liste des objets à faire pivoter</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationObjects</name>
+ <message>
+ <source>Total number of objects</source>
+ <translation>Nombre total d'objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiRotation:MultiRotationReversed</name>
+ <message>
+ <source>Reverse angular copy</source>
+ <translation>Copie angulaire inverse</translation>
+ </message>
+ <message>
+ <source>Reversed</source>
+ <translation>Renversé</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMultiTranslation</name>
+ <message>
+ <source>Copy objects and move</source>
+ <translation>Copier des objets et les déplacer</translation>
+ </message>
+ <message>
+ <source>Direction</source>
+ <translation>Direction</translation>
+ </message>
+ <message>
+ <source>Linear copy</source>
+ <translation>Copie linéaire</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationEndPoint</name>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ <message>
+ <source>Final point of translation</source>
+ <translation>Dernier point de translation</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationList</name>
+ <message>
+ <source>Segments:</source>
+ <translation>Segments:</translation>
+ </message>
+ <message>
+ <source>Select list of objects to be translated</source>
+ <translation>Sélectionner la liste des objets à translater</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationObjects</name>
+ <message>
+ <source>Total number of objects</source>
+ <translation>Nombre total d'objets</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:MultiTranslationStartPoint</name>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ <message>
+ <source>Start point of translation</source>
+ <translation>Point de départ de la translation</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMultiTranslation:ValueType</name>
+ <message>
+ <source>Full value</source>
+ <translation>Pleine valeur</translation>
+ </message>
+ <message>
+ <source>Single value</source>
+ <translation>Valeur unique</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchPoint</name>
+ <message>
+ <source>Create point</source>
+ <translation>Créer un point</translation>
+ </message>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchPoint:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchProjection</name>
+ <message>
+ <source>Project feature onto sketch plane</source>
+ <translation>Projeter une entité sur un plan d'esquisse</translation>
+ </message>
+ <message>
+ <source>Projection</source>
+ <translation>Projection</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:ExternalFeature</name>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Select external edge or vertex.</source>
+ <translation>Sélectionnez une arête externe ou un sommet.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:ExternalFeature:SketchPlugin_ProjectionValidator</name>
+ <message>
+ <source>The attribute with the %1 type is not processed</source>
+ <translation>Un argument de type %1 de la fonctionnalité de projection n'est pas pris en charge</translation>
+ </message>
+ <message>
+ <source>The attribute %1 should be an edge or vertex</source>
+ <translation>L'élément projeté doit être une arête ou un sommet</translation>
+ </message>
+ <message>
+ <source>There is no sketch referring to the current feature</source>
+ <translation>La fonction de projection n'a pas d'esquisse</translation>
+ </message>
+ <message>
+ <source>Unable to project feature from the same sketch</source>
+ <translation>Les fonctions de l'esquisse en cours ne peuvent pas être projetées</translation>
+ </message>
+ <message>
+ <source>Error: Line is orthogonal to the sketch plane.</source>
+ <translation>Erreur : La ligne est orthogonale au plan d'esquisse.</translation>
+ </message>
+ <message>
+ <source>Error: Circle is orthogonal to the sketch plane.</source>
+ <translation>Erreur : Le cercle est orthogonal au plan d'esquisse.</translation>
+ </message>
+ <message>
+ <source>Error: Arc is orthogonal to the sketch plane.</source>
+ <translation>Erreur : L'arc est orthogonal au plan d'esquisse.</translation>
+ </message>
+ <message>
+ <source>Error: Ellipse is orthogonal to the sketch plane.</source>
+ <translation>Erreur : L’ellipse est orthogonal au plan d'esquisse.</translation>
+ </message>
+ <message>
+ <source>Error: Elliptic Arc is orthogonal to the sketch plane.</source>
+ <translation>Erreur : L'arc elliptique est orthogonal au plan d'esquisse.</translation>
+ </message>
+ <message>
+ <source>Error: Selected object is not supported for projection.</source>
+ <translation>Erreur : L'objet sélectionné n'est pas pris en charge pour la projection.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchProjection:IncludeToResult</name>
+ <message>
+ <source>Include into the sketch result</source>
+ <translation>Inclure dans le résultat de l'esquisse</translation>
+ </message>
+ <message>
+ <source>Include projected feature into the sketch result</source>
+ <translation>Inclure la fonctionnalité projetée dans le résultat de l'esquisse</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchRectangle</name>
+ <message>
+ <source>Create rectangle</source>
+ <translation>Créer un rectangle</translation>
+ </message>
+ <message>
+ <source>Rectangle</source>
+ <translation>Rectangle</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:Auxiliary</name>
+ <message>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <source>Construction element</source>
+ <translation>Élément de construction</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchSplit</name>
+ <message>
+ <source>Cut selected segment arc or circle on existing coincident points</source>
+ <translation>Couper l'arc ou le cercle du segment sélectionné sur les points coïncidents existants</translation>
+ </message>
+ <message>
+ <source>Split</source>
+ <translation>Diviser</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchSplit:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez un segment à diviser dans la vue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchSplit:SelectedObject</name>
+ <message>
+ <source>Segment</source>
+ <translation>Segment</translation>
+ </message>
+ <message>
+ <source>Select segment for split</source>
+ <translation>Sélectionnez le segment à diviser</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchSplit:SelectedObject:SketchPlugin_SplitValidator</name>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Erreur inconnue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchSplit:SelectedObject</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionnez le segment à diviser</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchTrim</name>
+ <message>
+ <source>Trim</source>
+ <translation>Réduire</translation>
+ </message>
+ <message>
+ <source>Trim selected segment arc or circle on intersection points nearest to the graphic selection</source>
+ <translation>Couper l'arc ou le cercle du segment sélectionné sur les points d'intersection les plus proches de la sélection graphique</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchTrim:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>L'attribut "%1" n'est pas initialisé.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchTrim:SelectedObject</name>
+ <message>
+ <source>Segment</source>
+ <translation>Segment</translation>
+ </message>
+ <message>
+ <source>Select segment for trim</source>
+ <translation>Sélectionner un segment pour la coupe</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchTrim:SelectedObject:SketchPlugin_TrimValidator</name>
+ <message>
+ <source>Unknown error.</source>
+ <translation>Erreur inconnue.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchTrim:SelectedObject</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Sélectionner un segment pour la coupe</translation>
+ </message>
+ </context>
+
+</TS>
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+
+from EventsAPI import *
+from ModelAPI import *
+
+class FreeShapesListener(EventsAPI.Events_Listener):
+ def __init__(self):
+ Events_Listener.__init__(self)
+ # register as a listener
+ Events_Loop.loop().registerListener(self, Events_Loop.eventByName("DoFObjects"))
+ self.myEventProcessed = False
+
+ def __del__(self):
+ Events_Loop.loop().removeListener(self)
+
+ def processEvent(self, theMessage):
+ message = messageToUpdatedMessage(theMessage)
+ objs = message.objects()
+ assert(len(objs) == 3)
+ self.myEventProcessed = True
+
+
+if __name__ == "__main__":
+ # create the listener
+ listener = FreeShapesListener()
+
+ model.begin()
+ partSet = model.moduleDocument()
+ Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+ SketchLine_1 = Sketch_1.addLine(10, 10, -10, 10)
+ SketchLine_2 = Sketch_1.addLine(-10, 10, -10, -10)
+ SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+ SketchLine_3 = Sketch_1.addLine(-10, -10, 10, -10)
+ SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+ SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint())
+ SketchConstraintRigid_2 = Sketch_1.setFixed(SketchLine_3.endPoint())
+ model.end()
+
+ # send message to find the free shapes in the sketch
+ event = Events_Loop.eventByName("GetDoFObjects")
+ ModelAPI_EventCreator.get().sendUpdated(Sketch_1.feature(), event);
+ Events_Loop.loop().flush(event);
+
+ assert(listener.myEventProcessed)
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+
+from EventsAPI import *
+from ModelAPI import *
+
+class FreeShapesListener(EventsAPI.Events_Listener):
+ def __init__(self):
+ Events_Listener.__init__(self)
+ # register as a listener
+ Events_Loop.loop().registerListener(self, Events_Loop.eventByName("DoFObjects"))
+ self.myEventProcessed = False
+
+ def __del__(self):
+ Events_Loop.loop().removeListener(self)
+
+ def processEvent(self, theMessage):
+ message = messageToUpdatedMessage(theMessage)
+ objs = message.objects()
+ assert(len(objs) == 4)
+ self.myEventProcessed = True
+
+
+if __name__ == "__main__":
+ # create the listener
+ listener = FreeShapesListener()
+
+ model.begin()
+ partSet = model.moduleDocument()
+ Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+ SketchLine_1 = Sketch_1.addLine(10, 10, -10, 10)
+ SketchLine_2 = Sketch_1.addLine(-10, 10, -10, -10)
+ SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+ SketchLine_3 = Sketch_1.addLine(-10, -10, 10, -10)
+ SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+ SketchConstraintRigid_1 = Sketch_1.setFixed(SketchLine_1.startPoint())
+ SketchConstraintRigid_2 = Sketch_1.setFixed(SketchLine_3.endPoint())
+ SketchCircle_1 = Sketch_1.addCircle(-10, 10, 10)
+ SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchCircle_1.center())
+ SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10)
+ model.end()
+
+ # send message to find the free shapes in the sketch
+ event = Events_Loop.eventByName("GetDoFObjects")
+ ModelAPI_EventCreator.get().sendUpdated(Sketch_1.feature(), event);
+ Events_Loop.loop().flush(event);
+
+ assert(listener.myEventProcessed)
model.do()
# changing the parameter
-for param in range(-30, 31, 2):
+for param in range(-31, 30, 2):
if param == 0:
continue
DistanceParam.setValue(param)
model.do()
# changing the parameter
-for param in range(-30, 31, 2):
+for param in range(-31, 30, 2):
if param == 0:
continue
DistanceParam.setValue(param)
for param in range(-30, 31, 2):
DistanceParam.setValue(param)
model.do()
- if param <= 0:
+ if param < 0:
assert SketchConstraintDistance_1.feature().error() != '', "ERROR: Sketch should not be valid due to negative distance value"
+ elif param == 0: # constraint is valid, but lead to degenerated geometry
+ assert Sketch_1.feature().error() != '', "ERROR: Sketch should not be valid due to negative distance value"
else:
dist = model.distancePointPoint(firstPoint, secondPoint)
assert math.fabs(dist - math.fabs(param)) < TOLERANCE, "Incorrect distance {}, expected {}".format(dist, math.fabs(param))
#=========================================================================
# Change a distance value
#=========================================================================
-d = DISTANCE1 + 20.
+d = DISTANCE1 + 21.
dStep = -5.
while d >= -30.:
aSession.startOperation()
DISTANCE1 = d
aDistance.setValue(DISTANCE1)
aSession.finishOperation()
- if DISTANCE1 == 0:
- assert(aHDist1.error() != "")
- else:
- assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
d += dStep
assert (model.dof(aSketchFeature) == 3)
# Change a distance value (check previous constraint is applied too)
#=========================================================================
d = DISTANCE2
-dStep = -5.
+dStep = -7.
while d >= -50.:
aSession.startOperation()
DISTANCE2 = d
aDistance.setValue(DISTANCE2)
aSession.finishOperation()
- if DISTANCE2 == 0:
- assert(aHDist2.error() != "")
- else:
- assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
- assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
- assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ assert math.fabs(horizontalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.x() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected x = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert math.fabs(horizontalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
d += dStep
assert (model.dof(aSketchFeature) == 2)
# Change a distance value
#=========================================================================
d = DISTANCE3
-dStep = -5.
+dStep = -7.
while d >= -50.:
aSession.startOperation()
DISTANCE3 = d
aDistance.setValue(DISTANCE3)
aSession.finishOperation()
- if DISTANCE3 == 0:
- assert(aHDist3.error() != "")
- else:
- assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3)
+ assert math.fabs(horizontalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(horizontalDistance(aStartPoint, aEndPoint), DISTANCE3)
d += dStep
assert (model.dof(aSketchFeature) == 6)
--- /dev/null
+# Copyright (C) 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
+#
+
+"""
+ Test the zero value of the constraint "DistanceHorizontal"
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+from SketchAPI import *
+
+__updated__ = "2019-10-22"
+TOLERANCE = 1.e-6
+
+class TestZeroDistanceHorizontal(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myLine1 = self.mySketch.addLine(10, 10, 45, 27.5)
+ self.myLine2 = self.mySketch.addLine(20, 15, 30, 40)
+ self.myLine3 = self.mySketch.addLine(10, 0, 10, 10)
+ model.do()
+ self.myDOF = 12
+
+ def tearDown(self):
+ model.end()
+ model.checkSketch(self.mySketch, self.myDOF)
+
+ def assertDistanceHorizontal(self, theObject1, theObject2, theDistance):
+ dist = theObject2.x() - theObject1.x()
+ self.assertTrue(math.fabs(dist - theDistance) < TOLERANCE, "Current distance = {}, reference = {}".format(dist, theDistance))
+ model.checkSketch(self.mySketch, self.myDOF)
+
+
+ def test_distance_positive_nzznz(self):
+ """ Test 1. Change distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setHorizontalDistance(self.myLine1.startPoint(), self.myLine2.startPoint(), 10)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine2.startPoint(), 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine2.startPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine2.startPoint(), 10)
+
+ def test_distance_negative_nzznz(self):
+ """ Test 2. Change distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setHorizontalDistance(self.myLine1.endPoint(), self.myLine2.endPoint(), 15)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.endPoint(), self.myLine2.endPoint(), -15)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.endPoint(), self.myLine2.endPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.endPoint(), self.myLine2.endPoint(), -10)
+
+ def test_distance_equal_znzz(self):
+ """ Test 3. Change distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setHorizontalDistance(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine3.endPoint(), 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+
+ def test_distance_notequal_znzz(self):
+ """ Test 4. Change distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setHorizontalDistance(self.myLine1.startPoint(), self.myLine3.startPoint(), 0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine3.startPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine3.startPoint(), 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceHorizontal(self.myLine1.startPoint(), self.myLine3.startPoint(), 0)
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
+ assert model.checkPythonDump()
#=========================================================================
# Change a distance value
#=========================================================================
-d = DISTANCE1 + 20.
+d = DISTANCE1 + 21.
dStep = -5.
while d >= -30.:
aSession.startOperation()
DISTANCE1 = d
aDistance.setValue(DISTANCE1)
aSession.finishOperation()
- if DISTANCE1 == 0:
- assert(aVDist1.error() != "")
- else:
- assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
d += dStep
assert (model.dof(aSketchFeature) == 3)
# Change a distance value (check previous constraint is applied too)
#=========================================================================
d = DISTANCE2
-dStep = -5.
+dStep = -7.
while d >= -50.:
aSession.startOperation()
DISTANCE2 = d
aDistance.setValue(DISTANCE2)
aSession.finishOperation()
- if DISTANCE2 == 0:
- assert(aVDist2.error() != "")
- else:
- assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
- assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
- assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
+ assert math.fabs(verticalDistance(anExtCoords, aPoint1Coords) - DISTANCE2) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(anExtCoords, aPoint1Coords), DISTANCE2)
+ assert math.fabs(aPoint1Coords.y() - DISTANCE2) < 1.e-5, "Wrong point coordinates ({}, {}), expected y = {}".format(aPoint1Coords.x(), aPoint1Coords.y(), DISTANCE2)
+ assert math.fabs(verticalDistance(aPoint1Coords, aPoint2Coords) - DISTANCE1) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aPoint1Coords, aPoint2Coords), DISTANCE1)
d += dStep
assert (model.dof(aSketchFeature) == 2)
# Change a distance value
#=========================================================================
d = DISTANCE3
-dStep = -5.
+dStep = -7.
while d >= -50.:
aSession.startOperation()
DISTANCE3 = d
aDistance.setValue(DISTANCE3)
aSession.finishOperation()
- if DISTANCE3 == 0:
- assert(aVDist3.error() != "")
- else:
- assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3)
+ assert math.fabs(verticalDistance(aStartPoint, aEndPoint) - DISTANCE3) < 1.e-5, "Distance values are different: {0} != {1}".format(verticalDistance(aStartPoint, aEndPoint), DISTANCE3)
d += dStep
assert (model.dof(aSketchFeature) == 6)
--- /dev/null
+# Copyright (C) 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
+#
+
+"""
+ Test the zero value of the constraint "DistanceVertical"
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+from SketchAPI import *
+
+__updated__ = "2019-10-22"
+TOLERANCE = 1.e-6
+
+class TestZeroDistanceVertical(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myLine1 = self.mySketch.addLine(10, 10, 45, 27.5)
+ self.myLine2 = self.mySketch.addLine(20, 15, 30, 40)
+ self.myLine3 = self.mySketch.addLine(0, 10, 10, 10)
+ model.do()
+ self.myDOF = 12
+
+ def tearDown(self):
+ model.end()
+ model.checkSketch(self.mySketch, self.myDOF)
+
+ def assertDistanceVertical(self, theObject1, theObject2, theDistance):
+ dist = theObject2.y() - theObject1.y()
+ self.assertTrue(math.fabs(dist - theDistance) < TOLERANCE, "Current distance = {}, reference = {}".format(dist, theDistance))
+ model.checkSketch(self.mySketch, self.myDOF)
+
+
+ def test_distance_positive_nzznz(self):
+ """ Test 1. Change distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setVerticalDistance(self.myLine1.startPoint(), self.myLine2.startPoint(), 5)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine2.startPoint(), 5)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine2.startPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine2.startPoint(), 10)
+
+ def test_distance_negative_nzznz(self):
+ """ Test 2. Change distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setVerticalDistance(self.myLine1.endPoint(), self.myLine2.startPoint(), 12.5)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceVertical(self.myLine1.endPoint(), self.myLine2.startPoint(), -12.5)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.endPoint(), self.myLine2.startPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(12.5)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.endPoint(), self.myLine2.startPoint(), -12.5)
+
+ def test_distance_equal_znzz(self):
+ """ Test 3. Change distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setVerticalDistance(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine3.endPoint(), 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+
+ def test_distance_notequal_znzz(self):
+ """ Test 4. Change distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setVerticalDistance(self.myLine1.startPoint(), self.myLine3.startPoint(), 0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine3.startPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine3.startPoint(), 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistanceVertical(self.myLine1.startPoint(), self.myLine3.startPoint(), 0)
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
+ assert model.checkPythonDump()
--- /dev/null
+# Copyright (C) 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
+#
+
+"""
+ Test the zero value of the constraint "Distance"
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+from SketchAPI import *
+
+__updated__ = "2019-10-22"
+TOLERANCE = 1.e-6
+
+class TestZeroDistance(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myLine1 = self.mySketch.addLine(10, 10, 45, 27.5)
+ self.myLine2 = self.mySketch.addLine(20, 15, 30, 40)
+ self.myLine3 = self.mySketch.addLine(10, 0, 10, 10)
+ model.do()
+ self.myDOF = 12
+
+ def tearDown(self):
+ model.end()
+ model.checkSketch(self.mySketch, self.myDOF)
+
+ def assertDistance(self, theObject1, theObject2, theDistance, isSigned = False):
+ dist = -1.
+ if issubclass(type(theObject1), SketchAPI_SketchEntity):
+ if isSigned:
+ dist = model.signedDistancePointLine(theObject2, theObject1)
+ else:
+ dist = model.distancePointLine(theObject2, theObject1)
+ elif issubclass(type(theObject2), SketchAPI_SketchEntity):
+ if isSigned:
+ dist = model.signedDistancePointLine(theObject1, theObject2)
+ else:
+ dist = model.distancePointLine(theObject1, theObject2)
+ else:
+ dist = model.distancePointPoint(theObject1, theObject2)
+ self.assertTrue(math.fabs(dist - theDistance) < TOLERANCE, "Current distance = {}, reference = {}".format(dist, theDistance))
+ model.checkSketch(self.mySketch, self.myDOF)
+
+
+ def test_distance_points_nzznz(self):
+ """ Test 1. Change point-point distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setDistance(self.myLine1.endPoint(), self.myLine2.endPoint(), 20)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine1.endPoint(), self.myLine2.endPoint(), 20)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine1.endPoint(), self.myLine2.endPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(20)
+ self.myDOF += 1
+ model.do()
+ self.assertDistance(self.myLine1.endPoint(), self.myLine2.endPoint(), 20)
+
+ def test_distance_points_znzz(self):
+ """ Test 2. Change point-point distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setDistance(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+ self.myDOF -= 2
+ model.do()
+ self.assertDistance(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ self.myDOF += 1
+ model.do()
+ self.assertDistance(self.myLine1.startPoint(), self.myLine3.endPoint(), 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine1.startPoint(), self.myLine3.endPoint(), 0)
+
+
+ def test_unsigned_distance_nzznz(self):
+ """ Test 3. Change unsigned point-line distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setDistance(self.myLine1.result(), self.myLine2.endPoint(), 20)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine2.endPoint(), 20)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine2.endPoint(), 0)
+
+ SketchAPI_Constraint(dist).setValue(20)
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine2.endPoint(), 20)
+
+ def test_unsigned_distance_znzz(self):
+ """ Test 4. Change unsigned point-line distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setDistance(self.myLine2.startPoint(), self.myLine1.result(), 0)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine2.startPoint(), self.myLine1, 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistance(self.myLine2.startPoint(), self.myLine1, 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistance(self.myLine2.startPoint(), self.myLine1, 0)
+
+
+ def test_signed_distance_nzznz(self):
+ """ Test 5. Change signed point-line distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setDistance(self.myLine1.result(), self.myLine2.endPoint(), 20, True)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine2.endPoint(), -20, True)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine2.endPoint(), 0, True)
+
+ SketchAPI_Constraint(dist).setValue(20)
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine2.endPoint(), -20, True)
+
+ def test_signed_distance_nzznz_2(self):
+ """ Test 6. Change signed point-line distance from non-zero to zero and back to non-zero
+ """
+ dist = self.mySketch.setDistance(self.myLine3.startPoint(), self.myLine1.result(), 10, True)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine3.startPoint(), 10, True)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine3.startPoint(), 0, True)
+
+ SketchAPI_Constraint(dist).setValue(20)
+ model.do()
+ self.assertDistance(self.myLine1, self.myLine3.startPoint(), 20, True)
+
+ def test_signed_distance_znzz(self):
+ """ Test 7. Change signed point-line distance from zero to non-zero and back to zero
+ """
+ dist = self.mySketch.setDistance(self.myLine2.startPoint(), self.myLine1.result(), 0, True)
+ self.myDOF -= 1
+ model.do()
+ self.assertDistance(self.myLine2.startPoint(), self.myLine1, 0)
+
+ SketchAPI_Constraint(dist).setValue(10)
+ model.do()
+ self.assertDistance(self.myLine2.startPoint(), self.myLine1, 10)
+
+ SketchAPI_Constraint(dist).setValue(0)
+ model.do()
+ self.assertDistance(self.myLine2.startPoint(), self.myLine1, 0)
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
+ assert model.checkPythonDump()
self.myDOF += 4
model.do()
- self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.mySketch.setTangent(aLine.result(), self.myEllipticArc.result())
self.myNbTangency += 1
self.myDOF -= 1
model.do()
--- /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
+#
+
+"""
+ Test movement of the sketch ellipse
+"""
+
+import unittest
+import math
+from GeomAPI import GeomAPI_Pnt2d
+from SketchAPI import *
+from salome.shaper import model
+
+__updated__ = "2019-10-15"
+
+class TestMoveEllipticArc(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myCenter = GeomAPI_Pnt2d(70., 50.)
+ self.myAxisPoint = GeomAPI_Pnt2d(100., 70.)
+ self.myStartPoint = GeomAPI_Pnt2d(75., 75.)
+ self.myEndPoint = GeomAPI_Pnt2d(45., 55.)
+ macroEllipticArc = self.mySketch.addEllipticArc(self.myCenter, self.myAxisPoint, self.myStartPoint, self.myEndPoint, False)
+ self.myDOF = 7
+ model.do()
+ self.checkDOF()
+ self.myEllipticArc = SketchAPI_EllipticArc(model.lastSubFeature(self.mySketch, "SketchEllipticArc"))
+ self.myMajorRadius = self.myEllipticArc.majorRadius().value()
+ self.myMinorRadius = self.myEllipticArc.minorRadius().value()
+
+ def tearDown(self):
+ self.checkDOF()
+ self.checkPointOnEllipse(self.myEllipticArc.startPoint(), self.myEllipticArc)
+ self.checkPointOnEllipse(self.myEllipticArc.endPoint(), self.myEllipticArc)
+ model.end()
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointCoordinates(self, thePoint, theCoordinates):
+ aCoord = []
+ if issubclass(type(theCoordinates), GeomAPI_Pnt2d):
+ aCoord = [theCoordinates.x(), theCoordinates.y()]
+ else:
+ aCoord = theCoordinates
+ DIGITS = 7 - math.floor(math.log10(math.hypot(aCoord[0], aCoord[1])))
+ self.assertAlmostEqual(thePoint.x(), aCoord[0], DIGITS)
+ self.assertAlmostEqual(thePoint.y(), aCoord[1], DIGITS)
+
+ def checkPointOnEllipse(self, theCoordinates, theEllipticArc):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ firstFocus2d = GeomAPI_Pnt2d(theEllipticArc.firstFocus().x(), theEllipticArc.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, point)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipticArc.secondFocus().x(), theEllipticArc.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, point)
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipticArc.majorRadius().value(), 7 - math.floor(math.log10(theEllipticArc.majorRadius().value())))
+
+ def fixMajorRadius(self):
+ self.mySketch.setDistance(self.myEllipticArc.center(), self.myEllipticArc.majorAxisPositive(), self.myMajorRadius)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ def fixMinorRadius(self):
+ self.mySketch.setDistance(self.myEllipticArc.center(), self.myEllipticArc.minorAxisPositive(), self.myMinorRadius)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ def fixPoint(self, thePoint):
+ self.mySketch.setFixed(thePoint)
+ self.myDOF -= 2
+ model.do()
+ self.checkDOF()
+
+
+ def test_move_center_free_ellipse(self):
+ """ Test 1. Movement of central point of a free elliptic arc
+ """
+ newPosition = [self.myCenter.x() + 20., self.myCenter.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), newPosition)
+
+ def test_move_free_ellipse(self):
+ """ Test 2. Movement of a free ellipse dragging the edge
+ """
+ newPosition = GeomAPI_Pnt2d(110., 80.)
+ self.mySketch.move(self.myEllipticArc.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), self.myCenter)
+ self.checkPointOnEllipse(newPosition, self.myEllipticArc)
+ self.assertNotEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_center_ellipse_fixed_major_radius(self):
+ """ Test 3. Movement of central point of ellipse with fixed major radius
+ """
+ self.fixMajorRadius()
+
+ newPosition = [self.myCenter.x() + 20., self.myCenter.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), newPosition)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_ellipse_fixed_major_radius(self):
+ """ Test 4. Movement of ellipse with fixed major radius
+ """
+ self.fixMajorRadius()
+
+ newPosition = GeomAPI_Pnt2d(80., 80.)
+ self.mySketch.move(self.myEllipticArc.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipticArc)
+ self.assertNotEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_center_ellipse_fixed_minor_radius(self):
+ """ Test 5. Movement of central point of ellipse with fixed minor radius
+ """
+ self.fixMinorRadius()
+
+ newPosition = [self.myCenter.x() + 20., self.myCenter.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), newPosition)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+
+ def test_move_ellipse_fixed_minor_radius(self):
+ """ Test 6. Movement of ellipse with fixed minor radius
+ """
+ self.fixMinorRadius()
+
+ newPosition = GeomAPI_Pnt2d(110., 80.)
+ self.mySketch.move(self.myEllipticArc.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipticArc)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_center_ellipse_fixed_center(self):
+ """ Test 7. Movement of central point of ellipse with fixed center (nothing should be changed)
+ """
+ self.fixPoint(self.myEllipticArc.center())
+
+ newPosition = [self.myCenter.x() + 20., self.myCenter.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), self.myCenter)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_ellipse_fixed_center(self):
+ """ Test 8. Movement of ellipse with fixed center
+ """
+ self.fixPoint(self.myEllipticArc.center())
+
+ newPosition = GeomAPI_Pnt2d(110., 80.)
+ self.mySketch.move(self.myEllipticArc.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipticArc)
+ self.assertNotEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_center_ellipse_fixed_focus(self):
+ """ Test 9. Movement of central point of ellipse with fixed focus
+ """
+ focus = [self.myEllipticArc.firstFocus().x(), self.myEllipticArc.firstFocus().y()]
+ self.fixPoint(self.myEllipticArc.firstFocus())
+
+ newPosition = GeomAPI_Pnt2d(self.myCenter.x() + 20., self.myCenter.y() + 10.)
+ self.mySketch.move(self.myEllipticArc.center(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), newPosition)
+ self.checkPointCoordinates(self.myEllipticArc.firstFocus(), focus)
+ self.assertNotEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_focus_ellipse_fixed_focus(self):
+ """ Test 10. Movement of a focus point of ellipse with fixed focus (nothing should be changed)
+ """
+ focus = [self.myEllipticArc.firstFocus().x(), self.myEllipticArc.firstFocus().y()]
+ self.fixPoint(self.myEllipticArc.firstFocus())
+
+ newPosition = GeomAPI_Pnt2d(focus[0] + 10., focus[1] + 10.)
+ self.mySketch.move(self.myEllipticArc.firstFocus(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.firstFocus(), focus)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_ellipse_fixed_focus(self):
+ """ Test 11. Movement of ellipse with fixed focus
+ """
+ focus = [self.myEllipticArc.firstFocus().x(), self.myEllipticArc.firstFocus().y()]
+ self.fixPoint(self.myEllipticArc.firstFocus())
+
+ newPosition = GeomAPI_Pnt2d(80., 90.)
+ self.mySketch.move(self.myEllipticArc.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipticArc)
+ self.checkPointCoordinates(self.myEllipticArc.firstFocus(), focus)
+ self.assertNotEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_fixed_ellipse(self):
+ """ Test 12. Trying to move fully fixed ellipse
+ """
+ self.mySketch.setFixed(self.myEllipticArc.results()[-1])
+ self.myDOF -= 7
+ model.do()
+ self.checkDOF()
+
+ newPosition = [110., 80.]
+ self.mySketch.move(self.myEllipticArc.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myEllipticArc.majorAxisPositive(), self.myAxisPoint)
+ self.checkPointCoordinates(self.myEllipticArc.startPoint(), self.myStartPoint)
+ self.checkPointCoordinates(self.myEllipticArc.endPoint(), self.myEndPoint)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+
+ def test_move_start_point_free_ellipse(self):
+ """ Test 13. Trying to move start point of elliptic arc
+ """
+ newPosition = [self.myStartPoint.x() + 10., self.myStartPoint.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.startPoint(), newPosition)
+
+ def test_move_end_point_free_ellipse(self):
+ """ Test 14. Trying to move end point of elliptic arc
+ """
+ newPosition = [self.myEndPoint.x() - 10., self.myEndPoint.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.endPoint(), newPosition)
+
+ def test_move_start_point_fixed_ellipse(self):
+ """ Test 15. Trying to move start point of fully fixed ellipse
+ """
+ self.mySketch.setFixed(self.myEllipticArc.results()[-1])
+ self.myDOF -= 7
+ model.do()
+ self.checkDOF()
+
+ newPosition = [self.myStartPoint.x() + 10., self.myStartPoint.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.startPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myEllipticArc.majorAxisPositive(), self.myAxisPoint)
+ self.checkPointCoordinates(self.myEllipticArc.startPoint(), self.myStartPoint)
+ self.checkPointCoordinates(self.myEllipticArc.endPoint(), self.myEndPoint)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+
+ def test_move_end_point_fixed_ellipse(self):
+ """ Test 16. Trying to move end point of fully fixed ellipse
+ """
+ self.mySketch.setFixed(self.myEllipticArc.results()[-1])
+ self.myDOF -= 7
+ model.do()
+ self.checkDOF()
+
+ newPosition = [self.myEndPoint.x() - 10., self.myEndPoint.y() + 10.]
+ self.mySketch.move(self.myEllipticArc.endPoint(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipticArc.center(), self.myCenter)
+ self.checkPointCoordinates(self.myEllipticArc.majorAxisPositive(), self.myAxisPoint)
+ self.checkPointCoordinates(self.myEllipticArc.startPoint(), self.myStartPoint)
+ self.checkPointCoordinates(self.myEllipticArc.endPoint(), self.myEndPoint)
+ self.assertAlmostEqual(self.myEllipticArc.majorRadius().value(), self.myMajorRadius)
+ self.assertAlmostEqual(self.myEllipticArc.minorRadius().value(), self.myMinorRadius)
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
from ConfigAPI import *
Config_PropManager().registerProp("Visualization", "dimension_value_size", "Dimension value size", Config_Prop.IntSpin, "16")
+Config_PropManager().registerProp("Visualization", "sketch_dimension_color", "Dimension color", Config_Prop.Color, "64,128,255")
model.begin()
partSet = model.moduleDocument()
--- /dev/null
+# Copyright (C) 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
+#
+
+from salome.shaper import model
+
+from EventsAPI import *
+from ModelAPI import *
+
+class FreeShapesListener(EventsAPI.Events_Listener):
+ def __init__(self):
+ Events_Listener.__init__(self)
+ # register as a listener
+ Events_Loop.loop().registerListener(self, Events_Loop.eventByName("DoFObjects"))
+ self.myEventProcessed = False
+
+ def __del__(self):
+ Events_Loop.loop().removeListener(self)
+
+ def processEvent(self, theMessage):
+ message = messageToUpdatedMessage(theMessage)
+ objs = message.objects()
+ assert(len(objs) == 1)
+ assert(objectToFeature(objs[0]).getKind() == "SketchCircle")
+ self.myEventProcessed = True
+
+
+if __name__ == "__main__":
+ # create the listener
+ listener = FreeShapesListener()
+
+ model.begin()
+ partSet = model.moduleDocument()
+ Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+ SketchCircle_1 = Sketch_1.addCircle(-30, 0, 14)
+ SketchLine_1 = Sketch_1.addLine(-30, 0, 0, 0)
+ SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_1.startPoint())
+ SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Origin"), False)
+ SketchPoint_1 = SketchProjection_1.createdFeature()
+ SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+ SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+ SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 30)
+ model.end()
+
+ # send message to find the free shapes in the sketch
+ event = Events_Loop.eventByName("GetDoFObjects")
+ ModelAPI_EventCreator.get().sendUpdated(Sketch_1.feature(), event);
+ Events_Loop.loop().flush(event);
+
+ assert(listener.myEventProcessed)
- **Show free points** check box - highlights free points in the current sketch if it is checked.
- **Automatic constraints** - automatically create horizontal or vertical constraints if angle between created line and horizontal or vertical less then angular tolerance (defined in preferences).
- **Change sketch plane** button - allows to change working plane of the current sketch.
+- **Show remaining DoFs** button - highlights all sketch edges which are not fully constrained.
Now it is possible to:
.. _sketch_operations:
+Overconstraned state
+--------------------
+
+Sketcher comes into overconstrained state when an extra constraint was defined. The following picture shows an example of the overconstrained state:
+
+.. image:: images/Overconstrained.png
+ :align: center
+
+.. centered::
+ Overconstrained Sketch
+
+When Sketcher becomes into the state then:
+
+- buttons Apply and Cancel for the whole Sketcher are blocked;
+- a constraint which causes the overconstraint state is highlightid by red color;
+- a warning message in sketcher Property Panel is shown with recomendation what to do in this case;
+- an additional Undo button is shown under the warning messages;
+
+After undoing the last operation or deletion of a conflicting constraint Sketcher will become into a normal state.
+
Operations
----------
Operations modify existing features of the sketch or create new ones by copying them.
<sketch-start-label id="External" geometrical_selection="true" title="Select a plane on which to create a sketch" tooltip="Select a plane on which to create a sketch">
<validator id="GeomValidators_Face" parameters="plane"/>
</sketch-start-label>
- <!-- <label id="SolverDOF"/> -->
- <label id="SolverError" styleSheet="color : red; font : bold"/>
+ <undo_label id="SolverError" isHTML="true" />
<validator id="SketchPlugin_SolverErrorValidator"/>
</feature>
helpfile="pointFeature.html">
<sketch-2dpoint_selector id="PointCoordinates" accept_expressions="0" title="Point" tooltip="Point coordinates"
enable_value="enable_by_preferences"/>
- <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0" change_visual_attributes="true"/>
</feature>
<!-- SketchLine -->
enable_value="enable_by_preferences"/>
<labelvalue id="LineLength" accept_expressions="0" label="Length" default="computed" icon="icons/Sketch/distance_value.png"
tooltip="Line length" obligatory="0" enable_value="false"/>
- <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0" change_visual_attributes="true"/>
<validator id="GeomValidators_Different" parameters="StartPoint,EndPoint"/>
</feature>
</group>
accept_expressions="0"
enable_value="enable_by_preferences">
</labelvalue>
- <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0" change_visual_attributes="true"/>
</feature>
<!-- SketchMacroCircle -->
<feature id="SketchMacroCircle"
tooltip="Construction element"
label="Auxiliary"
default="false"
- obligatory="0"/>
+ obligatory="0"
+ change_visual_attributes="true"/>
</feature>
<!-- SketchArc -->
label="Auxiliary"
tooltip="Construction element"
default="false"
- obligatory="0"/>
+ obligatory="0"
+ change_visual_attributes="true"/>
</feature>
<!-- SketchMacroArc -->
label="Auxiliary"
tooltip="Construction element"
default="false"
- obligatory="0"/>
+ obligatory="0"
+ change_visual_attributes="true"/>
</feature>
<!-- SketchFillet -->
accept_expressions="0"
enable_value="enable_by_preferences">
</labelvalue>
- <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0" change_visual_attributes="true"/>
</feature>
<!-- SketchMacroEllipse -->
<feature id="SketchMacroEllipse"
tooltip="Construction element"
label="Auxiliary"
default="false"
- obligatory="0"/>
+ obligatory="0"
+ change_visual_attributes="true"/>
</feature>
<!-- SketchEllipticArc is a hidden feature. It is created inside SketchMacroEllipse. -->
accept_expressions="0"
enable_value="enable_by_preferences">
</labelvalue>
- <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0" change_visual_attributes="true"/>
</feature>
<!-- SketchMacroEllipticArc -->
<feature id="SketchMacroEllipticArc"
tooltip="Construction element"
label="Auxiliary"
default="false"
- obligatory="0"/>
+ obligatory="0"
+ change_visual_attributes="true"/>
</feature>
</group>
use_sketch_plane="false">
<validator id="SketchPlugin_ProjectionValidator"/>
</sketch_shape_selector>
- <boolvalue id="IncludeToResult" label="Include into the sketch result" default="true" tooltip="Include projected feature into the sketch result"/>
+ <boolvalue id="IncludeToResult" label="Include into the sketch result" default="true" tooltip="Include projected feature into the sketch result"
+ change_visual_attributes="true"/>
<validator id="PartSet_ProjectionSelection"/>
</feature>
use_sketch_plane="false">
<validator id="SketchPlugin_IntersectionValidator"/>
</sketch_shape_selector>
- <boolvalue id="IncludeToResult" label="Include into the sketch result" default="true" tooltip="Include projected feature into the sketch result"/>
+ <boolvalue id="IncludeToResult" label="Include into the sketch result" default="true" tooltip="Include projected feature into the sketch result"
+ change_visual_attributes="true"/>
<validator id="PartSet_IntersectionSelection"/>
</feature>
</group>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
<validator id="PartSet_DifferentObjects"/>
<validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
- <validator id="PartSet_DifferentPoints" parameters="ConstraintEntityB"/>
</sketch_shape_selector>
<sketch_shape_selector
id="ConstraintEntityB"
<validator id="SketchPlugin_DistanceAttr" parameters="ConstraintEntityA"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
<validator id="GeomValidators_ShapeType" parameters="vertex,line"/>
- <validator id="PartSet_DifferentPoints" parameters="ConstraintEntityA"/>
</sketch_shape_selector>
<sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<doublevalue_editor label="Value" tooltip="Distance" id="ConstraintValue" default="computed" min="0">
- <validator id="GeomValidators_Positive"/>
+ <validator id="GeomValidators_Positive" parameters="-1.e-10"/>
</doublevalue_editor>
<module_choice id="LocationType"
<sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<doublevalue_editor label="Value" tooltip="Distance" id="DistanceValue" default="computed" min="0">
- <validator id="GeomValidators_Positive"/>
+ <validator id="GeomValidators_Positive" parameters="-1.e-10"/>
</doublevalue_editor>
<module_choice id="LocationType"
<sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<doublevalue_editor label="Value" tooltip="Distance" id="DistanceValue" default="computed" min="0">
- <validator id="GeomValidators_Positive"/>
+ <validator id="GeomValidators_Positive" parameters="-1.e-10"/>
</doublevalue_editor>
<module_choice id="LocationType"
<!-- SketchConstraintAngle -->
<feature id="SketchConstraintAngle" title="Angle" tooltip="Set fixed angle between two line segments" icon="icons/Sketch/angle_constr.png"
helpfile="angleFeature.html">
- <sketch_shape_selector id="ConstraintEntityA" label="Line 1" tooltip="Select a line" shape_types="edge" >
+ <sketch_feature_point_selector
+ id="ConstraintEntityA"
+ selection_attributes="ConstraintEntityA SelectedPointA"
+ label="Line 1"
+ tooltip="Select a line"
+ shape_types="edge"
+ use_external="true">
<validator id="GeomValidators_ShapeType" parameters="line"/>
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
- </sketch_shape_selector>
- <sketch_shape_selector id="ConstraintEntityB" label="Line 2" tooltip="Select a line" shape_types="edge" >
+ </sketch_feature_point_selector>
+ <sketch_feature_point_selector
+ id="ConstraintEntityB"
+ selection_attributes="ConstraintEntityB SelectedPointB"
+ label="Line 2"
+ tooltip="Select a line"
+ shape_types="edge"
+ use_external="true">
<validator id="GeomValidators_ShapeType" parameters="line"/>
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
- </sketch_shape_selector>
+ </sketch_feature_point_selector>
<sketch-2dpoint_flyout_selector id="ConstraintFlyoutValuePnt" default="computed" internal="1" obligatory="0"/>
<doublevalue_editor label="Value" tooltip="Angle" id="AngleValue" default="computed" min="0" max="360" />
<validator id="PartSet_AngleSelection"/>
SET(SKETCHSOLVER_TEXT_RESOURCES
SketchSolver_msg_en.ts
+ SketchSolver_msg_fr.ts
)
INCLUDE_DIRECTORIES(
double PlaneGCSSolver_ConstraintWrapper::value() const
{
- return myValueParam->value();
+ return myValueParam ? myValueParam->value() : 0.0;
}
GCSConstraintPtr aConstraint = *anIt;
aConstraint->setTag(anID);
myEquationSystem->addConstraint(aConstraint.get());
- myConstraints[theMultiConstraintID].insert(aConstraint);
if (anID > CID_UNKNOWN)
++anID;
}
+ myConstraints[theMultiConstraintID] = theConstraints;
if (theMultiConstraintID >= CID_UNKNOWN)
myDOF = -1;
{
ConstraintMap::iterator aFound = myConstraints.find(theID);
if (aFound != myConstraints.end()) {
- for (std::set<GCSConstraintPtr>::iterator anIt = aFound->second.begin();
+ for (std::list<GCSConstraintPtr>::iterator anIt = aFound->second.begin();
anIt != aFound->second.end(); ++anIt)
myEquationSystem->clearByTag((*anIt)->getTag());
myDiagnoseBeforeSolve = false;
}
+void PlaneGCSSolver_Solver::getFreeParameters(GCS::SET_pD& theFreeParams)
+{
+ if (myConstraints.empty())
+ theFreeParams.insert(myParameters.begin(), myParameters.end());
+ else {
+ GCS::VEC_pD aParametersCopy = myParameters;
+ ConstraintMap aConstraintCopy = myConstraints;
+
+ // clear the set of equations
+ clear();
+ // reset constraints
+ myParameters = aParametersCopy;
+ for (ConstraintMap::iterator anIt = aConstraintCopy.begin();
+ anIt != aConstraintCopy.end(); ++anIt)
+ addConstraint(anIt->first, anIt->second);
+
+ // parameters detection works for Dense QR only
+ GCS::QRAlgorithm aQRAlgo = myEquationSystem->qrAlgorithm;
+ myEquationSystem->qrAlgorithm = GCS::EigenDenseQR;
+ diagnose();
+ GCS::VEC_pD aFreeParams;
+ myEquationSystem->getDependentParams(aFreeParams);
+ theFreeParams.insert(aFreeParams.begin(), aFreeParams.end());
+ // revert QR decomposition algorithm
+ myEquationSystem->qrAlgorithm = aQRAlgo;
+ }
+
+ if (theFreeParams.empty())
+ return;
+
+ // find all equal parameters too
+ struct EqualParameters
+ {
+ typedef std::map<double*, std::list<GCS::SET_pD>::iterator> MapParamGroup;
+
+ std::list<GCS::SET_pD> myEqualParams;
+ MapParamGroup myGroups;
+
+ void add(double* theParam1, double* theParam2)
+ {
+ MapParamGroup::iterator aFound1 = myGroups.find(theParam1);
+ MapParamGroup::iterator aFound2 = myGroups.find(theParam2);
+
+ if (aFound1 == myGroups.end()) {
+ if (aFound2 == myGroups.end()) {
+ // create new group
+ myEqualParams.push_back(GCS::SET_pD());
+ std::list<GCS::SET_pD>::iterator aGroup = --myEqualParams.end();
+ aGroup->insert(theParam1);
+ aGroup->insert(theParam2);
+ myGroups[theParam1] = aGroup;
+ myGroups[theParam2] = aGroup;
+ }
+ else {
+ // add first parameter to the second group
+ aFound2->second->insert(theParam1);
+ myGroups[theParam1] = aFound2->second;
+ }
+ }
+ else {
+ if (aFound2 == myGroups.end()) {
+ // add second parameter to the first group
+ aFound1->second->insert(theParam2);
+ myGroups[theParam2] = aFound1->second;
+ }
+ else if (aFound1 != aFound2) {
+ // merge two groups
+ GCS::SET_pD aCopy = *(aFound2->second);
+ myEqualParams.erase(aFound2->second);
+ for (GCS::SET_pD::iterator anIt = aCopy.begin(); anIt != aCopy.end(); ++anIt)
+ myGroups[*anIt] = aFound1->second;
+ aFound1->second->insert(aCopy.begin(), aCopy.end());
+ }
+ }
+ }
+ } anEqualParams;
+
+ for (ConstraintMap::iterator anIt = myConstraints.begin(); anIt != myConstraints.end(); ++anIt)
+ for (std::list<GCSConstraintPtr>::iterator aCIt = anIt->second.begin();
+ aCIt != anIt->second.end(); ++aCIt) {
+ if ((*aCIt)->getTypeId() == GCS::Equal)
+ anEqualParams.add((*aCIt)->params()[0], (*aCIt)->params()[1]);
+ }
+
+ GCS::SET_pD aFreeParamsCopy = theFreeParams;
+ for (GCS::SET_pD::iterator anIt = aFreeParamsCopy.begin();
+ anIt != aFreeParamsCopy.end(); ++anIt) {
+ EqualParameters::MapParamGroup::iterator aFound = anEqualParams.myGroups.find(*anIt);
+ if (aFound != anEqualParams.myGroups.end())
+ theFreeParams.insert(aFound->second->begin(), aFound->second->end());
+ }
+}
+
void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary()
{
bool hasOnlyMovement = true;
/// \brief Check conflicting/redundant constraints and DoF
void diagnose(const GCS::Algorithm& theAlgo = GCS::DogLeg);
+ /// \brief Return the list of modifiable parameters
+ void getFreeParameters(GCS::SET_pD& theFreeParams);
+
/// \brief Degrees of freedom
int dof();
void removeFictiveConstraint();
private:
- typedef std::map<ConstraintID, std::set<GCSConstraintPtr> > ConstraintMap;
+ typedef std::map<ConstraintID, std::list<GCSConstraintPtr> > ConstraintMap;
GCS::VEC_pD myParameters; ///< list of unknowns
ConstraintMap myConstraints; ///< list of constraints
}
return PlaneGCSSolver_Solver::STATUS_OK;
}
+
+
+void PlaneGCSSolver_Storage::getUnderconstrainedGeometry(std::set<ObjectPtr>& theFeatures) const
+{
+ std::set<double*> aFreeParams;
+ mySketchSolver->getFreeParameters(aFreeParams);
+ if (aFreeParams.empty())
+ return;
+
+ for (std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
+ aFIt != myFeatureMap.end(); ++aFIt) {
+ if (!aFIt->second)
+ continue;
+ GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(aFIt->second);
+ for (GCS::SET_pD::iterator aPIt = aParams.begin(); aPIt != aParams.end(); ++aPIt)
+ if (aFreeParams.find(*aPIt) != aFreeParams.end()) {
+ theFeatures.insert(aFIt->first);
+ break;
+ }
+ }
+}
/// Reversed arcs should have the last parameter lesser than the first parameter.
virtual void adjustParametrizationOfArcs();
+ /// \brief Return list of features which are not fully constrained
+ virtual void getUnderconstrainedGeometry(std::set<ObjectPtr>& theFeatures) const;
+
private:
/// \brief Convert feature using specified builder.
EntityWrapperPtr createFeature(const FeaturePtr& theFeature,
#include <PlaneGCSSolver_PointWrapper.h>
#include <PlaneGCSSolver_Storage.h>
#include <PlaneGCSSolver_Tools.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
#include <SketchPlugin_ConstraintDistanceHorizontal.h>
#include <SketchPlugin_ConstraintDistanceVertical.h>
*(theOddPoint->y) = aProjectedPnt->y();
}
+static FeaturePtr getFeature(AttributeRefAttrPtr theRefAttr)
+{
+ ObjectPtr anObj;
+ if (theRefAttr->isObject())
+ anObj = theRefAttr->object();
+ else
+ anObj = theRefAttr->attr()->owner();
+ return ModelAPI_Feature::feature(anObj);
+}
+
+static void calculateDistanceDirection(const ConstraintPtr& theConstraint,
+ const StoragePtr& theStorage,
+ double& theDirX, double& theDirY)
+{
+ std::shared_ptr<GeomDataAPI_Dir> aDistDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theConstraint->attribute(SketchPlugin_ConstraintDistance::DIRECTION_ID()));
+ if (aDistDir && aDistDir->isInitialized()) {
+ theDirX = aDistDir->x();
+ theDirY = aDistDir->y();
+ if (fabs(theDirX) > tolerance || fabs(theDirY) > tolerance)
+ return;
+ }
+
+ AttributeRefAttrPtr aRefAttrA = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr aRefAttrB = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+
+ EntityWrapperPtr aEntityA = theStorage->entity(aRefAttrA);
+ EntityWrapperPtr aEntityB = theStorage->entity(aRefAttrB);
+
+ GCSPointPtr aPoint;
+ if (aEntityA->type() != ENTITY_LINE && aEntityB->type() != ENTITY_LINE) {
+ aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aEntityA)->point();
+ theDirX = 1.0;
+ theDirY = 0.0;
+
+ EdgeWrapperPtr anEdgeA = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(
+ theStorage->entity(getFeature(aRefAttrA)));
+ EdgeWrapperPtr anEdgeB = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(
+ theStorage->entity(getFeature(aRefAttrB)));
+
+ if (anEdgeA && anEdgeB) {
+ GCS::DeriVector2 aDirA = anEdgeA->entity()->CalculateNormal(*aPoint);
+ GCS::DeriVector2 aDirB = anEdgeB->entity()->CalculateNormal(*aPoint);
+ double x = -aDirA.x + aDirB.x;
+ double y = -aDirA.y + aDirB.y;
+ double norm = sqrt(x*x + y*y);
+ if (norm > tolerance) {
+ theDirX = x / norm;
+ theDirY = y / norm;
+ }
+ }
+ }
+}
+
+static void moveEntity(const ConstraintPtr& theConstraint,
+ const StoragePtr& theStorage,
+ const double theDX, const double theDY)
+{
+ static const double THE_SHIFT = 1.e-4;
+
+ AttributeRefAttrPtr aRefAttrA = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr aRefAttrB = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+
+ EntityWrapperPtr aEntityA = theStorage->entity(aRefAttrA);
+ EntityWrapperPtr aEntityB = theStorage->entity(aRefAttrB);
+
+ PointWrapperPtr aPointA = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aEntityA);
+ PointWrapperPtr aPointB = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aEntityB);
+
+ if (aPointA) {
+ *aPointA->point()->x -= THE_SHIFT * theDX;
+ *aPointA->point()->y -= THE_SHIFT * theDY;
+ }
+ else if (aPointB) {
+ *aPointB->point()->x += THE_SHIFT * theDX;
+ *aPointB->point()->y += THE_SHIFT * theDY;
+ }
+}
+
+
void SketchSolver_ConstraintDistance::getAttributes(
EntityWrapperPtr& theValue,
return;
}
+ ScalarWrapperPtr aValue = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theValue);
+ bool isCoincidence = fabs(aValue->value()) < tolerance;
+
if (theAttributes[1]) {
if (myBaseConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
myType = CONSTRAINT_HORIZONTAL_DISTANCE;
else if (myBaseConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
myType = CONSTRAINT_VERTICAL_DISTANCE;
else
- myType = CONSTRAINT_PT_PT_DISTANCE;
+ myType = isCoincidence ? CONSTRAINT_PT_PT_COINCIDENT : CONSTRAINT_PT_PT_DISTANCE;
} else if (theAttributes[2] && theAttributes[2]->type() == ENTITY_LINE)
- myType = CONSTRAINT_PT_LINE_DISTANCE;
+ myType = isCoincidence ? CONSTRAINT_PT_ON_CURVE : CONSTRAINT_PT_LINE_DISTANCE;
else
theAttributes.clear();
+ if (myType == CONSTRAINT_HORIZONTAL_DISTANCE || myType == CONSTRAINT_VERTICAL_DISTANCE)
+ mySignValue = aValue->value() < 0.0 ? -1.0 : 1.0;
+
myPrevValue = 0.0;
- myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
+ if (isCoincidence)
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
+ else
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
}
void SketchSolver_ConstraintDistance::adjustConstraint()
ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint);
myPrevValue = aConstraint->value();
- SketchSolver_Constraint::update();
+ bool isDistanceAlognDir =
+ myBaseConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
+ myBaseConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID();
+
+ AttributeDoublePtr aCurValue = myBaseConstraint->real(SketchPlugin_Constraint::VALUE());
+ bool isZeroSwitch = fabs(myPrevValue) < tolerance && fabs(aCurValue->value()) > tolerance;
+ bool isNonZeroSwitch = fabs(myPrevValue) > tolerance && fabs(aCurValue->value()) < tolerance;
+
+ if (!isDistanceAlognDir && (isZeroSwitch || isNonZeroSwitch)) {
+ // the value is changed from non-zero to zero or vice versa
+ remove();
+ process();
+
+ // move entities to avoid conflicting constraints
+ if (isZeroSwitch) {
+ double aDirX, aDirY;
+ // calculate the direction basing on the distanced objects
+ calculateDistanceDirection(myBaseConstraint, myStorage, aDirX, aDirY);
+ moveEntity(myBaseConstraint, myStorage, aDirX, aDirY);
+
+ if (myOddPoint) {
+ removeConstraintsKeepingSign();
+ addConstraintsToKeepSign();
+ }
+ }
+ }
+ else {
+ SketchSolver_Constraint::update();
+ if (isDistanceAlognDir && mySignValue * aConstraint->value() < 0.0) {
+ if (isZeroSwitch)
+ aConstraint->setValue(-aConstraint->value());
+ else
+ mySignValue *= -1.0;
+ }
+ }
}
bool SketchSolver_ConstraintDistance::remove()
/// The value parameter for the constraint
inline static const std::string& CONSTRAINTS()
{
- static const std::string MY_ERROR_VALUE("The constraint is conflicting with others. "
- "To fix this, you can either undo your operation or remove a conflicting constraint.");
+ static const std::string MY_ERROR_VALUE("<b>The constraint is conflicting with others. "
+ "To fix this, you can either <font color='red'>undo (Ctrl+Z)</font> your operation or "
+ "<font color='red'>remove</font> a conflicting constraint.</b>");
return MY_ERROR_VALUE;
}
/// Cyclic dependency of copied features with their originals
inline static const std::string& INFINITE_LOOP()
{
static const std::string MY_ERROR_VALUE(
- "There is a circular reference between copied sketch entities and their originals. "
- "To fix this, you can either undo your operation or remove wrong constraint.");
+ "<b>There is a circular reference between copied sketch entities and their originals. "
+ "To fix this, you can either <font color='red'>undo (Ctrl+Z)</font> your operation or "
+ "<font color='red'>remove</font> wrong constraint.</b>");
return MY_ERROR_VALUE;
}
/// Constraints should use objects instead of features as attributes
return false;
return true;
}
+
+void SketchSolver_Group::underconstrainedFeatures(std::set<ObjectPtr>& theFeatures) const
+{
+ myStorage->getUnderconstrainedGeometry(theFeatures);
+}
*/
bool resolveConstraints();
+ /// \brief Find the list of features, which are not fully constrained.
+ void underconstrainedFeatures(std::set<ObjectPtr>& theFeatures) const;
+
/// \brief Block or unblock events sent by features in this group
void blockEvents(bool isBlocked);
////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED));
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS));
}
SketchSolver_Manager::~SketchSolver_Manager()
}
myIsComputed = false;
}
+ else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_GET_DOF_OBJECTS)) {
+ std::shared_ptr<ModelAPI_ObjectUpdatedMessage> anUpdateMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ std::set<ObjectPtr> aObjects = anUpdateMsg->objects();
+ if (aObjects.size() == 1) {
+ std::set<ObjectPtr>::const_iterator aIt;
+ for (aIt = aObjects.cbegin(); aIt != aObjects.cend(); aIt++) {
+ CompositeFeaturePtr aFeature =
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aIt);
+ if (aFeature) {
+ SketchGroupPtr aGroup = findGroup(aFeature);
+
+ std::set<ObjectPtr> aFreeFeatures;
+ aGroup->underconstrainedFeatures(aFreeFeatures);
+
+ std::list<ObjectPtr> aFeatures;
+ std::set<ObjectPtr>::const_iterator aIt;
+ for (aIt = aFreeFeatures.cbegin(); aIt != aFreeFeatures.cend(); ++aIt) {
+ aFeatures.push_back(*aIt);
+ }
+
+ // send features to GUI
+ static const Events_ID anEvent = Events_Loop::eventByName(EVENT_DOF_OBJECTS);
+ ModelAPI_EventCreator::get()->sendUpdated(aFeatures, anEvent);
+ Events_Loop::loop()->flush(anEvent);
+ }
+ }
+ }
+ }
// resolve constraints if needed
bool needToUpdate = needToResolve && resolveConstraints();
// Purpose: search groups of entities interacting with given feature
// ============================================================================
SketchGroupPtr SketchSolver_Manager::findGroup(
- std::shared_ptr<SketchPlugin_Feature> theFeature)
+ std::shared_ptr<SketchPlugin_Feature> theFeature)
{
if (!isFeatureValid(theFeature))
return SketchGroupPtr(); // do not process wrong features
break;
}
}
+ return findGroup(aSketch);
+}
- if (!aSketch)
+SketchGroupPtr SketchSolver_Manager::findGroup(CompositeFeaturePtr theSketch)
+{
+ if (!theSketch)
return SketchGroupPtr(); // not a sketch's feature
std::list<SketchGroupPtr>::const_iterator aGroupIt;
for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt)
- if ((*aGroupIt)->getWorkplane() == aSketch)
+ if ((*aGroupIt)->getWorkplane() == theSketch)
return *aGroupIt;
// group for the sketch does not created yet
- SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(aSketch));
+ SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(theSketch));
myGroups.push_back(aNewGroup);
return aNewGroup;
}
* \return Pointer to corresponding group or NULL if the group cannot be created.
*/
SketchGroupPtr findGroup(std::shared_ptr<SketchPlugin_Feature> theFeature);
+ /** \brief Searches group related to specified composite feature
+ * \param[in] theSketch sketch to be found
+ * \return Pointer to corresponding group or NULL if the group cannot be created.
+ */
+ SketchGroupPtr findGroup(std::shared_ptr<ModelAPI_CompositeFeature> theSketch);
/// \brief Stop sending the Update event until all features updated
/// \return \c true, if the last flushed event is Update
/// \brief Return list of conflicting constraints
std::set<ObjectPtr> getConflictingConstraints(SolverPtr theSolver) const;
+ /// \brief Return list of features which are not fully constrained
+ virtual void getUnderconstrainedGeometry(std::set<ObjectPtr>& theFeatures) const = 0;
+
/// \brief Verify, the sketch contains degenerated geometry
/// after resolving the set of constraints
/// \return STATUS_OK if the geometry is valid, STATUS_DEGENERATED otherwise.
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+ <context>
+ <name>Sketch</name>
+ <message>
+ <source>The constraint is conflicting with others. To fix this, you can either undo your operation or remove a conflicting constraint.</source>
+ <translation>La contrainte est en conflit avec les autres. Pour résoudre ce problème, vous pouvez annuler votre opération ou supprimer une contrainte en conflit.</translation>
+ </message>
+ <message>
+ <source>There is a circular reference between copied sketch entities and their originals. To fix this, you can either undo your operation or remove wrong constraint.</source>
+ <translation>Il existe une référence circulaire entre les entités d'esquisse copiées et leurs originaux. Pour résoudre ce problème, vous pouvez annuler votre opération ou supprimer une contrainte incorrecte.</translation>
+ </message>
+ <message>
+ <source>Caution: SolveSpace crashed! Constraints are wrong</source>
+ <translation>Attention : Plantage de SolveSpace ! Les contraintes sont fausses</translation>
+ </message>
+ <message>
+ <source>The set of constraints lead to degenerated geometry. To fix this, you can either undo your operation or remove a constraint or the degenerated geometry.</source>
+ <translation>L'ensemble des contraintes conduit à une géométrie dégénérée. Pour résoudre ce problème, vous pouvez annuler votre opération ou supprimer une contrainte ou la géométrie dégénérée..</translation>
+ </message>
+ </context>
+</TS>
new GeomAPI_Angle2d(aLine1, isReversed1, aLine2, isReversed2));
}
- gp_Pnt2d aFirstPoint = anAng->firstPoint()->impl<gp_Pnt2d>();
+ gp_Pnt2d aCenterPoint = anAng->center()->impl<gp_Pnt2d>();
+ gp_Pnt2d aFirstPoint, aSecondPoint;
+ if (anAng->angleRadian() > 0.0) {
+ aFirstPoint = anAng->firstPoint()->impl<gp_Pnt2d>();
+ aSecondPoint = anAng->secondPoint()->impl<gp_Pnt2d>();
+ }
+ else {
+ aFirstPoint = anAng->secondPoint()->impl<gp_Pnt2d>();
+ aSecondPoint = anAng->firstPoint()->impl<gp_Pnt2d>();
+ }
+
+
std::shared_ptr<GeomAPI_Pnt> aPoint = thePlane->to3D(aFirstPoint.X(), aFirstPoint.Y());
theFirstPoint = aPoint->impl<gp_Pnt>();
- gp_Pnt2d aCenterPoint = anAng->center()->impl<gp_Pnt2d>();
aPoint = thePlane->to3D(aCenterPoint.X(), aCenterPoint.Y());
theCenterPoint = aPoint->impl<gp_Pnt>();
- gp_Pnt2d aSecondPoint = anAng->secondPoint()->impl<gp_Pnt2d>();
aPoint = thePlane->to3D(aSecondPoint.X(), aSecondPoint.Y());
theSecondPoint = aPoint->impl<gp_Pnt>();
{
if (!plane().get())
return;
+
+ DataPtr aData = myConstraint->data();
+
gp_Pnt aFirstPoint, aSecondPoint, aCenterPoint;
bool aReadyToDisplay = readyToDisplay(myConstraint, plane(),
aFirstPoint, aSecondPoint, aCenterPoint);
mySecondPoint = aSecondPoint;
myCenterPoint = aCenterPoint;
- DataPtr aData = myConstraint->data();
AttributeDoublePtr anAttributeValue =
aData->real(SketchPlugin_ConstraintAngle::ANGLE_VALUE_ID());
myValue.init(anAttributeValue);
myFlyOutPoint = aFlyoutPnt->impl<gp_Pnt>();
}
- DataPtr aData = myConstraint->data();
std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
ModelAPI_AttributeInteger>(aData->attribute(SketchPlugin_ConstraintAngle::TYPE_ID()));
SketcherPrs_Tools::AngleType anAngleType = (SketcherPrs_Tools::AngleType)(aTypeAttr->value());
switch (anAngleType) {
case SketcherPrs_Tools::ANGLE_DIRECT: {
#ifndef COMPILATION_CORRECTION
- SetArrowsVisibility(AIS_TOAV_Second);
+ SetArrowsVisibility(AIS_TOAV_Both);
#endif
SetMeasuredGeometry(myFirstPoint, myCenterPoint, mySecondPoint);
#ifndef COMPILATION_CORRECTION
break;
case SketcherPrs_Tools::ANGLE_BACKWARD: {
#ifndef COMPILATION_CORRECTION
- SetArrowsVisibility(AIS_TOAV_Second);
+ SetArrowsVisibility(AIS_TOAV_Both);
#endif
SetMeasuredGeometry(myFirstPoint, myCenterPoint, mySecondPoint);
bool isReversedPlanes = isAnglePlaneReversedToSketchPlane();
return readyToDisplay(theConstraint, thePlane, aPnt1, aPnt2);
}
+static bool isEqualPoints(ModelAPI_Feature* theConstraint,
+ const gp_Pnt& thePoint1,
+ const gp_Pnt& thePoint2)
+{
+ bool isEqual = false;
+ if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
+ isEqual = Abs(thePoint1.X() - thePoint2.X()) < Precision::Confusion();
+ else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
+ isEqual = Abs(thePoint1.Y() - thePoint2.Y()) < Precision::Confusion();
+ else
+ isEqual = thePoint1.SquareDistance(thePoint2) < Precision::SquareConfusion();
+ return isEqual;
+}
+
void SketcherPrs_LengthDimension::Compute(
const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
const Handle(Prs3d_Presentation)& thePresentation,
gp_Pnt aPnt1, aPnt2;
bool aReadyToDisplay = readyToDisplay(myConstraint, plane(), aPnt1, aPnt2);
if (aReadyToDisplay) {
+ if (isEqualPoints(myConstraint, aPnt1, aPnt2)) {
+ // adjust points to draw the dimension presentation
+ std::shared_ptr<GeomDataAPI_Dir> aDirAttr = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ myConstraint->attribute(SketchPlugin_ConstraintDistance::DIRECTION_ID()));
+ double x = 0.0, y = 0.0;
+ if (aDirAttr && aDirAttr->isInitialized()) {
+ x = aDirAttr->x();
+ y = aDirAttr->y();
+ if (x == 0.0 && y == 0.0)
+ x = 1.0;
+ }
+ else if (myConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
+ y = 1.0;
+ else
+ x = 1.0;
+ GeomPointPtr aCoord = plane()->to3D(x, y);
+
+ gp_XYZ aDir(aCoord->x(), aCoord->y(), aCoord->z());
+ aPnt1.ChangeCoord().Add(aDir * (-Precision::Confusion()));
+ aPnt2.ChangeCoord().Add(aDir * Precision::Confusion());
+ }
+
myFirstPoint = aPnt1;
mySecondPoint = aPnt2;
if (!aPnt_A || !aPnt_B) // Objects not found
return false;
- if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID()) {
+ /*if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID()) {
if (fabs(aPnt_A->x() - aPnt_B->x()) < Precision::Confusion())
return false;
}
else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
if (fabs(aPnt_A->y() - aPnt_B->y()) < Precision::Confusion())
return false;
- }
+ }*/
// Get points from these object
std::shared_ptr<GeomAPI_Pnt> aPoint1 = thePlane->to3D(aPnt_A->x(), aPnt_A->y());
aSizedMap->InitTrash(aPixMap->Format(), aWidth, aHeigh);
for (Standard_Size i = 0; i < aWidth; i++) {
for (Standard_Size j = 0; j < aHeigh; j++) {
- aSizedMap->SetPixelColor(i, j, aPixMap->PixelColor(i / aRatio, j / aRatio));
+ aSizedMap->SetPixelColor(int(i), int(j), aPixMap->PixelColor(i / aRatio, j / aRatio));
}
}
aPixMap = aSizedMap;
std::shared_ptr<GeomAPI_Pnt2d> getPoint(ModelAPI_Feature* theFeature,
const std::string& theAttribute)
{
- std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
+ std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theAttribute));
+ if (!aPointAttr.get() || !aPointAttr->isInitialized()) {
+ aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
theFeature, theAttribute, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
+ }
if (aPointAttr.get() != NULL)
return aPointAttr->pnt();
return std::shared_ptr<GeomAPI_Pnt2d>();
XGUI_ActiveControlSelector.h
XGUI_ColorDialog.h
XGUI_ContextMenuMgr.h
- XGUI_CustomPrs.h
XGUI_DataModel.h
XGUI_DeflectionDialog.h
XGUI_Displayer.h
XGUI_ActiveControlMgr.cpp
XGUI_ColorDialog.cpp
XGUI_ContextMenuMgr.cpp
- XGUI_CustomPrs.cpp
XGUI_DataModel.cpp
XGUI_DeflectionDialog.cpp
XGUI_Displayer.cpp
)
SET(TEXT_RESOURCES
-# XGUI_msg_fr.ts
+ XGUI_msg_fr.ts
)
SET(PROJECT_LIBRARIES
IF (${UPDATE_TRANSLATION})
- SET(PROJECT_FILES ${PROJECT_SOURCES} ${ROJECT_HEADERS} )
+ SET(PROJECT_FILES ${PROJECT_SOURCES} ${PROJECT_HEADERS} )
QT5_CREATE_TRANSLATION(QM_RESOURCES
${PROJECT_FILES}
${TEXT_RESOURCES}
- OPTIONS -extensions cpp -no-recursive
+ OPTIONS -extensions cpp -no-recursive -locations none
)
ELSE(${UPDATE_TRANSLATION})
- QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ IF(${MAKE_TRANSLATION})
+ QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ ENDIF(${MAKE_TRANSLATION})
ENDIF(${UPDATE_TRANSLATION})
SET(PROJECT_INCLUDES
${PROJECT_SOURCE_DIR}/src/Events
${PROJECT_SOURCE_DIR}/src/Config
+ ${PROJECT_SOURCE_DIR}/src/ExchangePlugin
${PROJECT_SOURCE_DIR}/src/ModelAPI
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/ModuleBase
#include <ModuleBase_IModule.h>
#include <ModuleBase_Tools.h>
-#include <ModuleBase_OperationAction.h>
+#include <ModuleBase_Operation.h>
#include <ModuleBase_ViewerPrs.h>
#include <QAction>
aDesktop, this, SLOT(onRename()));
addAction("RENAME_CMD", aAction);
- aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move.png"),
+ aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_to_end.png"),
XGUI_Workshop::MOVE_TO_END_COMMAND, this);
addAction("MOVE_CMD", aAction);
+ aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_to_end_split.png"),
+ XGUI_Workshop::MOVE_TO_END_SPLIT_COMMAND, this);
+ addAction("MOVE_SPLIT_CMD", aAction);
+
aAction = ModuleBase_Tools::createAction(QIcon(":pictures/clean_history.png"),
tr("Clean history"), aDesktop);
addAction("CLEAN_HISTORY_CMD", aAction);
if (!(hasParameter || hasFeature))
action("SHOW_ONLY_CMD")->setEnabled(true);
}
- else if (hasFeature && myWorkshop->canMoveFeature())
+ else if (hasFeature && myWorkshop->canMoveFeature()) {
action("MOVE_CMD")->setEnabled(true);
+ action("MOVE_SPLIT_CMD")->setEnabled(true);
+ }
if( aMgr->activeDocument() == aObject->document() )
{
action("SHADING_CMD")->setEnabled(true);
action("WIREFRAME_CMD")->setEnabled(true);
}
- if (hasFeature && myWorkshop->canMoveFeature())
+ if (hasFeature && myWorkshop->canMoveFeature()) {
action("MOVE_CMD")->setEnabled(true);
+ action("MOVE_SPLIT_CMD")->setEnabled(true);
+ }
} // end multi-selection
// Check folder management commands state if only features are selected
aList.append(action("RENAME_CMD"));
aList.append(action("SHOW_RESULTS_CMD"));
aList.append(action("MOVE_CMD"));
+ aList.append(action("MOVE_SPLIT_CMD"));
aList.append(mySeparator1);
aList.append(action("INSERT_FOLDER_CMD"));
aList.append(action("ADD_TO_FOLDER_BEFORE_CMD"));
aActions.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
aActions.append(mySeparator3);
aActions.append(action("MOVE_CMD"));
+ aActions.append(action("MOVE_SPLIT_CMD"));
aActions.append(action("COLOR_CMD"));
aActions.append(action("DEFLECTION_CMD"));
aActions.append(action("TRANSPARENCY_CMD"));
+++ /dev/null
-// Copyright (C) 2014-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 <XGUI_CustomPrs.h>
-#include <XGUI_Workshop.h>
-#include <XGUI_Displayer.h>
-
-#include <ModuleBase_IModule.h>
-
-#include <ModelAPI_AttributeIntArray.h>
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_Session.h>
-#include <ModelAPI_ResultBody.h>
-#include <ModelAPI_ResultConstruction.h>
-
-#include <GeomAPI_ShapeExplorer.h>
-
-#include <Config_PropManager.h>
-
-#include <Events_InfoMessage.h>
-
-#include <vector>
-#include <QColor>
-
-double getDeflection(const ResultPtr& theResult)
-{
- double aDeflection = -1;
- // get deflection from the attribute of the result
- if (theResult.get() != NULL &&
- theResult->data()->attribute(ModelAPI_Result::DEFLECTION_ID()).get() != NULL) {
- AttributeDoublePtr aDoubleAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
- if (aDoubleAttr.get() && aDoubleAttr->isInitialized()) {
- double aValue = aDoubleAttr->value();
- if (aValue > 0) /// zero value should not be used as a deflection(previous studies)
- aDeflection = aDoubleAttr->value();
- }
- }
- return aDeflection;
-}
-
-void getColor(const ResultPtr& theResult, std::vector<int>& theColor)
-{
- theColor.clear();
- // get color from the attribute of the result
- if (theResult.get() != NULL &&
- theResult->data()->attribute(ModelAPI_Result::COLOR_ID()).get() != NULL) {
- AttributeIntArrayPtr aColorAttr = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
- if (aColorAttr.get() && aColorAttr->size()) {
- theColor.push_back(aColorAttr->value(0));
- theColor.push_back(aColorAttr->value(1));
- theColor.push_back(aColorAttr->value(2));
- }
- }
-}
-
-void XGUI_CustomPrs::getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
- std::vector<int>& theColor)
-{
- theColor.clear();
- // get default color from the preferences manager for the given result
- if (theColor.empty()) {
- std::string aSection, aName, aDefault;
- theObject->colorConfigInfo(aSection, aName, aDefault);
- if (!aSection.empty() && !aName.empty()) {
- theColor = Config_PropManager::color(aSection, aName);
- }
- }
- if (!isEmptyColorValid && theColor.empty()) {
- // all AIS objects, where the color is not set, are in black.
- // The color should be defined in XML or set in the attribute
- theColor = Config_PropManager::color("Visualization", "object_default_color");
- Events_InfoMessage("XGUI_CustomPrs",
- "A default color is not defined in the preferences for this kind of result").send();
- }
-}
-
-double XGUI_CustomPrs::getDefaultDeflection(const ObjectPtr& theObject)
-{
- double aDeflection = -1;
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
- if (aResult.get()) {
- bool isConstruction = false;
-
- std::string aResultGroup = aResult->groupName();
- if (aResultGroup == ModelAPI_ResultConstruction::group())
- isConstruction = true;
- else if (aResultGroup == ModelAPI_ResultBody::group()) {
- GeomShapePtr aGeomShape = aResult->shape();
- if (aGeomShape.get()) {
- // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
- // correction of deviation for them should not influence to the application performance
- GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
- isConstruction = !anExp.more();
- }
- }
- if (isConstruction)
- aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
- else
- aDeflection = Config_PropManager::real("Visualization", "body_deflection");
- }
- return aDeflection;
-}
-
-double getTransparency(const ResultPtr& theResult)
-{
- double aTransparency = -1;
- // get transparency from the attribute of the result
- if (theResult.get() != NULL &&
- theResult->data()->attribute(ModelAPI_Result::TRANSPARENCY_ID()).get() != NULL) {
- AttributeDoublePtr aDoubleAttr = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
- if (aDoubleAttr.get() && aDoubleAttr->isInitialized()) {
- aTransparency = aDoubleAttr->value();
- }
- }
- return aTransparency;
-}
-
-double getDefaultTransparency(const ResultPtr& theResult)
-{
- return Config_PropManager::integer("Visualization", "shaper_default_transparency") / 100.;
-}
-
-XGUI_CustomPrs::XGUI_CustomPrs(XGUI_Workshop* theWorkshop)
-: myWorkshop(theWorkshop)
-{
-}
-
-void XGUI_CustomPrs::getResultColor(const ResultPtr& theResult, std::vector<int>& theColor)
-{
- getColor(theResult, theColor);
- if (theColor.empty())
- getDefaultColor(theResult, false, theColor);
-}
-
-double XGUI_CustomPrs::getResultDeflection(const ResultPtr& theResult)
-{
- double aDeflection = getDeflection(theResult);
- if (aDeflection < 0)
- aDeflection = getDefaultDeflection(theResult);
- return aDeflection;
-}
-
-double XGUI_CustomPrs::getResultTransparency(const ResultPtr& theResult)
-{
- double aTransparency = getTransparency(theResult);
- if (aTransparency < 0)
- aTransparency = getDefaultTransparency(theResult);
- return aTransparency;
-}
-
-bool XGUI_CustomPrs::customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
- std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs)
-{
- bool aCustomized = false;
- if (theResult.get()) {
- std::vector<int> aColor;
- getResultColor(theResult, aColor);
-
- SessionPtr aMgr = ModelAPI_Session::get();
- if (aMgr->activeDocument() != theResult->document()) {
- QColor aQColor(aColor[0], aColor[1], aColor[2]);
- QColor aNewColor =
- QColor::fromHsvF(aQColor.hueF(), aQColor.saturationF()/3., aQColor.valueF());
- aColor[0] = aNewColor.red();
- aColor[1] = aNewColor.green();
- aColor[2] = aNewColor.blue();
- }
- aCustomized = !aColor.empty() && thePrs->setColor(aColor[0], aColor[1], aColor[2]);
-
- aCustomized = thePrs->setDeflection(getResultDeflection(theResult)) | aCustomized;
-
- aCustomized = thePrs->setTransparency(getResultTransparency(theResult)) | aCustomized;
- }
- ModuleBase_IModule* aModule = myWorkshop->module();
- aCustomized = aModule->customisePresentation(theResult, thePrs, theCustomPrs) || aCustomized;
- return aCustomized;
-}
+++ /dev/null
-// Copyright (C) 2014-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 XGUI_CustomPrs_H
-#define XGUI_CustomPrs_H
-
-#include "XGUI.h"
-#include <GeomAPI_ICustomPrs.h>
-#include <GeomAPI_AISObject.h>
-#include <ModelAPI_Result.h>
-
-class XGUI_Workshop;
-
-/**
-* Interface of a class which can provide specific customization of
-* object presentation
-*/
-class XGUI_CustomPrs : public GeomAPI_ICustomPrs
-{
-public:
- /// Constructor
- /// \param theWorkshop the current workshop instance
- XGUI_EXPORT XGUI_CustomPrs(XGUI_Workshop* theWorkshop);
-
- XGUI_EXPORT virtual ~XGUI_CustomPrs() {};
-
- /// Modifies the given presentation in the custom way.
- virtual bool customisePresentation(ResultPtr theResult, AISObjectPtr thePrs,
- std::shared_ptr<GeomAPI_ICustomPrs> theCustomPrs);
-
- /// Returns color of a result object
- /// \param theResult a result object
- /// \param theColor a color in form of RGB vector
- static void getResultColor(const ResultPtr& theResult, std::vector<int>& theColor);
-
- /// Returns deflection of a result object
- /// \param theResult a result object
- /// \return theDeflection a real value
- static double getResultDeflection(const ResultPtr& theResult);
-
- /// Returns transparency of a result object
- /// \param theResult a result object
- /// \return theTransparency a real value
- static double getResultTransparency(const ResultPtr& theResult);
-
- /// Returns the default object color. It obtains colorConfigInfo of the object
- /// and find it in preferences. If there are no this color in preference and an empty
- /// color is interpreted as invalid, it shows error message
- /// \param theObject an investigated object
- /// \param isEmptyColorValid boolean state about interpretation of empty color
- /// \param theColor the result color
- static void XGUI_EXPORT getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
- std::vector<int>& theColor);
-
- /// Returns the default deflection value. The value is obtained from the application preferences
- /// \param theObject an investigated object
- /// \return deflection value
- static double XGUI_EXPORT getDefaultDeflection(const ObjectPtr& theObject);
-
-protected:
- XGUI_Workshop* myWorkshop; ///< the current workshop
-};
-
-#endif
#include "XGUI_Displayer.h"
-#include "XGUI_CustomPrs.h"
#include "XGUI_FacesPanel.h"
#include "XGUI_Selection.h"
#include "XGUI_SelectionActivate.h"
#include <ModuleBase_BRepOwner.h>
#include <ModuleBase_IModule.h>
#include <ModuleBase_Preferences.h>
-#include <ModuleBase_ResultPrs.h>
#include <ModuleBase_Tools.h>
#include <ModuleBase_ViewerPrs.h>
#include <ModuleBase_IViewer.h>
//**************************************************************
XGUI_Displayer::XGUI_Displayer(XGUI_Workshop* theWorkshop)
: myWorkshop(theWorkshop), myNeedUpdate(false),
- myViewerBlockedRecursiveCount(0), myIsFirstAISContextUse(true)
+ myViewerBlockedRecursiveCount(0), myContextId(0)
{
- myCustomPrs = std::shared_ptr<GeomAPI_ICustomPrs>(new XGUI_CustomPrs(theWorkshop));
}
//**************************************************************
}
anAIS = aPrs->getAISObject(anAIS);
} else {
- Handle(AIS_InteractiveObject) anAISPrs =
- myWorkshop->module()->createPresentation(theObject);
- if (anAISPrs.IsNull()) {
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
- if (aResult.get() != NULL) {
- std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
- if (aShapePtr.get() != NULL) {
- anAISPrs = new ModuleBase_ResultPrs(aResult);
- }
- }
- }
- Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
- if (!aShapePrs.IsNull())
- ModuleBase_Tools::setPointBallHighlighting((AIS_Shape*)aShapePrs.get());
- anAIS = AISObjectPtr(new GeomAPI_AISObject());
- anAIS->setImpl(new Handle(AIS_InteractiveObject)(anAISPrs));
+ anAIS = myWorkshop->module()->createPresentation(theObject);
isShading = true;
}
- if (anAIS)
+ if (anAIS.get())
aDisplayed = display(theObject, anAIS, isShading, theUpdateViewer);
}
return aDisplayed;
if (!anAISIO.IsNull()) {
appendResultObject(theObject, theAIS);
- bool isCustomized = customizeObject(theObject);
+ //bool isCustomized = customizeObject(theObject);
int aDispMode = isShading? Shading : Wireframe;
if (isShading)
bool XGUI_Displayer::redisplay(ObjectPtr theObject, bool theUpdateViewer)
{
bool aRedisplayed = false;
+ Handle(AIS_InteractiveContext) aContext = AISContext();
+ if (aContext.IsNull())
+ return aRedisplayed;
+
if (!isVisible(theObject))
return aRedisplayed;
AISObjectPtr aAISObj = getAISObject(theObject);
- Handle(AIS_InteractiveObject) aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
+ Handle(AIS_InteractiveObject) aAISIO;
GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
if (aPrs) {
}
aAISIO = aAIS_Obj->impl<Handle(AIS_InteractiveObject)>();
}
+ else {
+ aAISIO = aAISObj->impl<Handle(AIS_InteractiveObject)>();
+ }
- Handle(AIS_InteractiveContext) aContext = AISContext();
- if (!aContext.IsNull() && !aAISIO.IsNull()) {
- // Check that the visualized shape is the same and the redisplay is not necessary
- // Redisplay of AIS object leads to this object selection compute and the selection
- // in the browser is lost
- // this check is not necessary anymore because the selection store/restore is realized
- // before and after the values modification.
- // Moreother, this check avoids customize and redisplay presentation if the presentable
- // parameter is changed.
- bool isEqualShapes = false;
+ if (!aAISIO.IsNull()) {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
- if (aResult.get() != NULL) {
- Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aAISIO);
- if (!aShapePrs.IsNull()) {
- std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
- if (aShapePtr.get()) {
- const TopoDS_Shape& aOldShape = aShapePrs->Shape();
- if (!aOldShape.IsNull())
- isEqualShapes = aOldShape.IsEqual(aShapePtr->impl<TopoDS_Shape>());
- }
+ if (aResult.get()) {
+ // Set color
+ std::vector<int> aColor;
+ ModelAPI_Tools::getColor(aResult, aColor);
+ if (aColor.size() > 0) {
+ Quantity_Color
+ aCol(aColor[0] / 255., aColor[1] / 255., aColor[2] / 255., Quantity_TOC_RGB);
+ aAISIO->SetColor(aCol);
}
+ // Set deflection
+ double aDeflection = ModelAPI_Tools::getDeflection(aResult);
+ if ((aDeflection >= 0) && (aDeflection != aAISObj->getDeflection()))
+ aAISObj->setDeflection(aDeflection);
+
+ // Set transparency
+ double aTransparency = ModelAPI_Tools::getTransparency(aResult);
+ if ((aTransparency >= 0) && (aTransparency != aAISObj->getTransparency()))
+ aAISObj->setTransparency(aTransparency);
}
- // Customization of presentation
- bool isCustomized = customizeObject(theObject);
- #ifdef DEBUG_FEATURE_REDISPLAY
- qDebug(QString("Redisplay: %1, isEqualShapes=%2, isCustomized=%3").
- arg(!isEqualShapes || isCustomized).arg(isEqualShapes)
- .arg(isCustomized).toStdString().c_str());
- #endif
- if (!isEqualShapes || isCustomized) {
- /// if shapes are equal and presentation are customized, selection should be restored
- bool aNeedToRestoreSelection = isEqualShapes && isCustomized;
- if (aNeedToRestoreSelection)
- myWorkshop->module()->storeSelection();
+ myWorkshop->module()->storeSelection();
#ifdef CLEAR_OUTDATED_SELECTION_BEFORE_REDISPLAY
- myWorkshop->selector()->deselectPresentation(aAISIO);
+ myWorkshop->selector()->deselectPresentation(aAISIO);
#endif
- if (aContext->IsDisplayed(aAISIO))
- aContext->Redisplay(aAISIO, false);
- else
- aContext->Display(aAISIO, false);
+ if (aContext->IsDisplayed(aAISIO))
+ aContext->Redisplay(aAISIO, false);
+ else {
+ aContext->Display(aAISIO, false);
+ }
#ifdef TINSPECTOR
if (getCallBack()) getCallBack()->Redisplay(aAISIO);
#endif
- if (aNeedToRestoreSelection)
- myWorkshop->module()->restoreSelection();
+ //if (aNeedToRestoreSelection)
+ myWorkshop->module()->restoreSelection();
- aRedisplayed = true;
- #ifdef DEBUG_FEATURE_REDISPLAY
- qDebug(" Redisplay happens");
- #endif
- if (theUpdateViewer)
- updateViewer();
- }
+ aRedisplayed = true;
+ #ifdef DEBUG_FEATURE_REDISPLAY
+ qDebug(" Redisplay happens");
+ #endif
+ if (theUpdateViewer)
+ updateViewer();
}
return aRedisplayed;
}
Handle(AIS_InteractiveContext) XGUI_Displayer::AISContext() const
{
Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
- if (!aContext.IsNull() && myIsFirstAISContextUse/*&& !aContext->HasOpenedContext()*/) {
- XGUI_Displayer* aDisplayer = (XGUI_Displayer*)this;
- aDisplayer->myIsFirstAISContextUse = false;
+ if (!aContext.IsNull() && (myContextId != aContext.get())) {
+ myContextId = aContext.get();
if (!myWorkshop->selectionActivate()->isTrihedronActive())
selectionActivate()->deactivateTrihedron(true);
aContext->DefaultDrawer()->VIsoAspect()->SetNumber(0);
aContext->DefaultDrawer()->UIsoAspect()->SetNumber(0);
- ModuleBase_IViewer::DefaultHighlightDrawer = aContext->HighlightStyle();
+ //Handle(AIS_Trihedron) aTrihedron = myWorkshop->viewer()->trihedron();
+ //aTrihedron->getHighlightPointAspect()->SetScale(2.0);
+ //aTrihedron->getHighlightPointAspect()->SetTypeOfMarker(Aspect_TOM_O_STAR);
+
// Commented out according to discussion in bug #2825
+ //ModuleBase_IViewer::DefaultHighlightDrawer = aContext->HighlightStyle();
//Handle(Prs3d_Drawer) aSelStyle = aContext->SelectionStyle();
//double aDeflection =
// QString(ModelAPI_ResultConstruction::DEFAULT_DEFLECTION().c_str()).toDouble();
return aContext;
}
+//**************************************************************
+void XGUI_Displayer::setSelectionColor(const std::vector<int>& theColor)
+{
+ Handle(AIS_InteractiveContext) aContext = AISContext();
+ if (!aContext.IsNull()) {
+ Quantity_Color aQColor(theColor[0] / 255.,
+ theColor[1] / 255.,
+ theColor[2] / 255., Quantity_TOC_RGB);
+ aContext->SelectionStyle()->SetColor(aQColor);
+ aContext->SelectionStyle()->PointAspect()->SetColor(aQColor);
+ aContext->SelectionStyle()->LineAspect()->SetColor(aQColor);
+ aContext->HighlightStyle(Prs3d_TypeOfHighlight_LocalSelected)->SetColor(aQColor);
+ }
+}
+
+
+//**************************************************************
+std::vector<int> XGUI_Displayer::selectionColor() const
+{
+ std::vector<int> aColor;
+ Handle(AIS_InteractiveContext) aContext = AISContext();
+ if (!aContext.IsNull()) {
+ Quantity_Color aQColor = aContext->SelectionStyle()->Color();
+ aColor.push_back((int)(aQColor.Red() * 255));
+ aColor.push_back((int)(aQColor.Green() * 255));
+ aColor.push_back((int)(aQColor.Blue() * 255));
+ }
+ return aColor;
+}
+
+
//**************************************************************
Handle(SelectMgr_AndFilter) XGUI_Displayer::GetFilter()
{
}
//**************************************************************
-bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
-{
- AISObjectPtr anAISObj = getAISObject(theObject);
- // correct the result's color it it has the attribute
- ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
-
- // Customization of presentation
- GeomCustomPrsPtr aCustomPrs;
- FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- if (aFeature.get() != NULL) {
- GeomCustomPrsPtr aCustPrs = std::dynamic_pointer_cast<GeomAPI_ICustomPrs>(aFeature);
- if (aCustPrs.get() != NULL)
- aCustomPrs = aCustPrs;
- }
- if (aCustomPrs.get() == NULL) {
- GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
- // we ignore presentable not customized objects
- if (aPrs.get() == NULL)
- aCustomPrs = myCustomPrs;
- }
- bool isCustomized = aCustomPrs.get() &&
- aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs);
- isCustomized = myWorkshop->module()->afterCustomisePresentation(aResult, anAISObj, myCustomPrs)
- || isCustomized;
-
- // update presentation state if faces panel is active
- if (anAISObj.get() && myWorkshop->facesPanel())
- isCustomized = myWorkshop->facesPanel()->customizeObject(theObject, anAISObj) || isCustomized;
-
- return isCustomized;
-}
+//bool XGUI_Displayer::customizeObject(ObjectPtr theObject)
+//{
+// AISObjectPtr anAISObj = getAISObject(theObject);
+// // correct the result's color it it has the attribute
+// ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+//
+// // Customization of presentation
+// GeomCustomPrsPtr aCustomPrs;
+// FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+// if (aFeature.get() != NULL) {
+// GeomCustomPrsPtr aCustPrs = std::dynamic_pointer_cast<GeomAPI_ICustomPrs>(aFeature);
+// if (aCustPrs.get() != NULL)
+// aCustomPrs = aCustPrs;
+// }
+// if (aCustomPrs.get() == NULL) {
+// GeomPresentablePtr aPrs = std::dynamic_pointer_cast<GeomAPI_IPresentable>(theObject);
+// // we ignore presentable not customized objects
+// if (aPrs.get() == NULL)
+// aCustomPrs = myCustomPrs;
+// }
+// bool isCustomized = aCustomPrs.get() &&
+// aCustomPrs->customisePresentation(aResult, anAISObj, myCustomPrs);
+// isCustomized = myWorkshop->module()->afterCustomisePresentation(aResult, anAISObj, myCustomPrs)
+// || isCustomized;
+//
+// // update presentation state if faces panel is active
+// if (anAISObj.get() && myWorkshop->facesPanel())
+// isCustomized = myWorkshop->facesPanel()->customizeObject(theObject, anAISObj) || isCustomized;
+//
+// return isCustomized;
+//}
//**************************************************************
QColor XGUI_Displayer::setObjectColor(ObjectPtr theObject,
#include "XGUI.h"
#include <GeomAPI_AISObject.h>
-#include <GeomAPI_ICustomPrs.h>
#include <GeomAPI_Pln.h>
#include <ModelAPI_Result.h>
/// Returns scale of active view
double getViewScale() const;
+ /// Set color of selection
+ /// \param theColor R,G,B values of color
+ void setSelectionColor(const std::vector<int>& theColor);
+
+ /// Returns current selection color
+ std::vector<int> selectionColor() const;
+
signals:
/// Signal on object display
/// \param theObject a data object
#endif
Handle(SelectMgr_AndFilter) myAndFilter; ///< A container for selection filters
- /// A default custom presentation, which is used if the displayed feature is not
- /// a custom presentation
- GeomCustomPrsPtr myCustomPrs;
-
/// Definition of a type of map which defines correspondance between objects and presentations
#ifdef OPTIMIZE_PRS
XGUI_TwoSidePresentationMap myResult2AISObjectMap; ///< A map of displayed objects
/// Number of blocking of the viewer update. The viewer is updated only if it is zero
int myViewerBlockedRecursiveCount;
- bool myIsFirstAISContextUse; ///< Flag: first asking of AIS context: trihedron activation
+ mutable void* myContextId;
mutable bool myNeedUpdate; ///< A flag that update was requested but not done
};
#include "XGUI_FacesPanel.h"
#include "XGUI_ObjectsBrowser.h"
#include "XGUI_SelectionMgr.h"
+#include "XGUI_Selection.h"
#include "XGUI_Tools.h"
#include "XGUI_Workshop.h"
+#include "XGUI_Displayer.h"
+#include "XGUI_ViewerProxy.h"
#include <ModuleBase_IModule.h>
#include <ModuleBase_ISelection.h>
#include <Config_PropManager.h>
#include <Events_Loop.h>
#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAPI_Shape.h>
#include <ModelAPI_Events.h>
+#include <ModelAPI_ResultGroup.h>
+#include <ModelAPI_AttributeSelectionList.h>
#include <QAction>
#include <QCheckBox>
static const int LayoutMargin = 3;
//********************************************************************
-XGUI_FacesPanel::XGUI_FacesPanel(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop)
+XGUI_FacesPanel::XGUI_FacesPanel(QWidget* theParent, XGUI_Workshop* theWorkshop)
: QDockWidget(theParent), myIsActive(false), myWorkshop(theWorkshop)
{
setWindowTitle(tr("Hide Faces"));
if (myLastItemIndex == 0) // do nothing because there was no activity in the pane after reset
return;
- // clear internal containers
- myListView->getControl()->clear();
- myItems.clear();
+ std::map<ObjectPtr, TopoDS_ListOfShape> anObjectToShapes;
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
+ QMap<int, std::shared_ptr<ModuleBase_ViewerPrs> >::const_iterator aIt;
+ for (aIt = myItems.cbegin(); aIt != myItems.cend(); aIt++) {
+ getObjectsMapFromPrs(aIt.value(), anObjectToShapes, anObjectToPrs);
+ }
- // restore previous view of presentations
- bool isModified = redisplayObjects(myItemObjects);
- std::set<std::shared_ptr<ModelAPI_Object> > aHiddenObjects = myHiddenObjects;
- isModified = displayHiddenObjects(aHiddenObjects, myHiddenObjects) || isModified;
- if (isModified)// && isToFlushRedisplay) // flush signal immediatelly until container is filled
+ std::set<ObjectPtr> aObjects;
+ TopoDS_ListOfShape anEmpty;
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs)>::const_iterator aPrsIt;
+ for (aPrsIt = anObjectToPrs.cbegin(); aPrsIt != anObjectToPrs.cend(); aPrsIt++) {
+ aObjects.insert(aPrsIt->first);
+ aPrsIt->second->setSubShapeHidden(anEmpty);
+ }
+ std::set<std::shared_ptr<ModelAPI_Object> >::const_iterator aGrpIt;
+ for (aGrpIt = myHiddenGroups.cbegin(); aGrpIt != myHiddenGroups.cend(); aGrpIt++)
+ (*aGrpIt)->setDisplayed(true);
+ myHiddenGroups.clear();
+
+ if (redisplayObjects(aObjects))
flushRedisplay();
+ // clear internal containers
+ myListView->getControl()->clear();
+ myItems.clear();
updateProcessedObjects(myItems, myItemObjects);
- myHiddenObjects.clear();
myLastItemIndex = 0; // it should be after redisplay as flag used in customize
+ myHiddenObjects.clear();
}
//********************************************************************
ModuleBase_IModule* aModule = myWorkshop->module();
QIntList aModuleSelectionFilters = myWorkshop->module()->selectionFilters();
- theSelectionFilters.Append(aModule->selectionFilter(SF_GlobalFilter));
+ // The global filter makes problem for groups selection when any operation is launched
+ // theSelectionFilters.Append(aModule->selectionFilter(SF_GlobalFilter));
theSelectionFilters.Append(aModule->selectionFilter(SF_FilterInfinite));
theSelectionFilters.Append(aModule->selectionFilter(SF_ResultGroupNameFilter));
}
// selection should be cleared after emit of signal to do not process selection change
// event by the previous selector
// the selection is cleared by activating selection control
- XGUI_Tools::workshop(myWorkshop)->selector()->clearSelection();
+ myWorkshop->selector()->clearSelection();
}
else
emit deactivated();
return myHiddenOrTransparent->isChecked();
}
+//********************************************************************
+double XGUI_FacesPanel::transparency() const
+{
+ return useTransparency() ?
+ Config_PropManager::real("Visualization", "hidden_face_transparency") : 1;
+}
+
+
//********************************************************************
void XGUI_FacesPanel::restoreObjects(const std::set<ObjectPtr>& theHiddenObjects)
{
}
}
+//********************************************************************
+void XGUI_FacesPanel::getObjectsMapFromPrs(ModuleBase_ViewerPrsPtr thePrs,
+ std::map<ObjectPtr, TopoDS_ListOfShape>& theObjectToShapes,
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) >& theObjectToPrs)
+{
+ ObjectPtr anObject = thePrs->object();
+ if (!anObject.get())
+ return;
+
+ XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+ ResultGroupPtr aResGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anObject);
+ if (aResGroup.get()) {
+ // Process a grouip result
+ FeaturePtr aGroupFeature = ModelAPI_Feature::feature(aResGroup);
+ AttributeSelectionListPtr aSelectionList = aGroupFeature->selectionList("group_list");
+ AISObjectPtr aPrs;
+ for (int i = 0; i < aSelectionList->size(); i++) {
+ AttributeSelectionPtr aSelection = aSelectionList->value(i);
+ ResultPtr aRes = aSelection->context();
+ aPrs = aDisplayer->getAISObject(aRes);
+ if (aPrs.get()) {
+ Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
+ aPrs->impl<Handle(AIS_InteractiveObject)>());
+ if (!aResultPrs.IsNull()) {
+ GeomShapePtr aShape = aSelection->value();
+ if (theObjectToShapes.find(aRes) != theObjectToShapes.end())
+ theObjectToShapes.at(aRes).Append(aShape->impl<TopoDS_Shape>());
+ else {
+ TopoDS_ListOfShape aListOfShapes;
+ aListOfShapes.Append(aShape->impl<TopoDS_Shape>());
+ theObjectToShapes[aRes] = aListOfShapes;
+ theObjectToPrs[aRes] = aResultPrs;
+ }
+ }
+ }
+ }
+ }
+ else {
+ // Process bodies
+ Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
+ thePrs->interactive());
+ if (aResultPrs.IsNull())
+ return;
+
+ if (theObjectToShapes.find(anObject) != theObjectToShapes.end())
+ theObjectToShapes.at(anObject).Append(ModuleBase_Tools::getSelectedShape(thePrs));
+ else {
+ TopoDS_ListOfShape aListOfShapes;
+ aListOfShapes.Append(ModuleBase_Tools::getSelectedShape(thePrs));
+ theObjectToShapes[anObject] = aListOfShapes;
+ theObjectToPrs[anObject] = aResultPrs;
+ }
+ }
+}
+
//********************************************************************
void XGUI_FacesPanel::processSelection()
{
- QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(
- ModuleBase_ISelection::Viewer);
+ QList<ModuleBase_ViewerPrsPtr> aSelected =
+ myWorkshop->selector()->selection()->getSelected(ModuleBase_ISelection::Viewer);
+
+ if (aSelected.size() == 0)
+ return;
+
bool isModified = false;
static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- std::map<ObjectPtr, NCollection_List<TopoDS_Shape> > anObjectToShapes;
+ std::map<ObjectPtr, TopoDS_ListOfShape> anObjectToShapes;
std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
+ std::set<int> aToRemove;
+
for (int i = 0; i < aSelected.size(); i++) {
ModuleBase_ViewerPrsPtr aPrs = aSelected[i];
ObjectPtr anObject = aPrs->object();
if (!anObject.get())
continue;
- if (ModuleBase_Tools::getSelectedShape(aPrs).ShapeType() != TopAbs_FACE)
- continue;
- Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
- aPrs->interactive());
- if (aResultPrs.IsNull())
- continue;
- QString aItemName = XGUI_Tools::generateName(aPrs);
+ ResultGroupPtr aResGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anObject);
+ if (aResGroup.get()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aResGroup);
+ if (aFeature.get()) {
+ AttributeSelectionListPtr aSelectionListAttr =
+ aFeature->data()->selectionList("group_list");
+ std::string aType = aSelectionListAttr->selectionType();
+ if (aType != "Faces")
+ continue;
+ }
+ }
+ else {
+ GeomShapePtr aShapePtr = aPrs->shape();
+ if (!aShapePtr.get() || !aShapePtr->isFace())
+ continue;
+ }
+
+ QString aItemName = aResGroup.get()?
+ aResGroup->data()->name().c_str() : XGUI_Tools::generateName(aPrs);
if (myListView->hasItem(aItemName))
- return;
+ continue;
+
+ getObjectsMapFromPrs(aPrs, anObjectToShapes, anObjectToPrs);
+ if (aResGroup.get() && aResGroup->isDisplayed()) {
+ aResGroup->setDisplayed(false);
+ myHiddenGroups.insert(aResGroup);
+ }
+
+ // The code is dedicated to remove already selected items if they are selected twice
+ // It can happen in case of groups selection
+ QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator aIt;
+ for (aIt = myItems.cbegin(); aIt != myItems.cend(); aIt++) {
+ ModuleBase_ViewerPrsPtr aPrs = aIt.value();
+ ObjectPtr aObject = aPrs->object();
+ ResultGroupPtr aResGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(aObject);
+ if (aResGroup.get())
+ continue;
+ if (anObjectToShapes.find(aObject) != anObjectToShapes.end()) {
+ TopoDS_ListOfShape aShapes = anObjectToShapes[aObject];
+ GeomShapePtr aShapePtr = aPrs->shape();
+ if (aShapes.Contains(aShapePtr->impl<TopoDS_Shape>())) {
+ aToRemove.insert(aIt.key());
+ }
+ }
+ }
myItems.insert(myLastItemIndex, aPrs);
myListView->addItem(aItemName, myLastItemIndex);
myLastItemIndex++;
isModified = true;
-
- if (anObjectToShapes.find(anObject) != anObjectToShapes.end())
- anObjectToShapes.at(anObject).Append(ModuleBase_Tools::getSelectedShape(aPrs));
- else {
- NCollection_List<TopoDS_Shape> aListOfShapes;
- aListOfShapes.Append(ModuleBase_Tools::getSelectedShape(aPrs));
- anObjectToShapes[anObject] = aListOfShapes;
- anObjectToPrs[anObject] = aResultPrs;
- }
}
- for (std::map<ObjectPtr, NCollection_List<TopoDS_Shape> >::const_iterator
- anIt = anObjectToShapes.begin(); anIt != anObjectToShapes.end(); anIt++) {
+
+ // Hide fully hidden shapes
+ std::map<ObjectPtr, TopoDS_ListOfShape>::const_iterator anIt;
+ for (anIt = anObjectToShapes.begin(); anIt != anObjectToShapes.end(); anIt++) {
ObjectPtr anObject = anIt->first;
if (!anObject.get() || anObjectToPrs.find(anObject) == anObjectToPrs.end())
continue;
}
ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
}
+
+ // Process selected presentations
+ double aTransp = transparency();
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs)>::iterator aPrsIt;
+ for (aPrsIt = anObjectToPrs.begin(); aPrsIt != anObjectToPrs.end(); aPrsIt++) {
+ ObjectPtr anObject = aPrsIt->first;
+ Handle(ModuleBase_ResultPrs) aPrs = aPrsIt->second;
+ TopoDS_ListOfShape aAlreadyHidden = aPrs->hiddenSubShapes();
+ TopoDS_ListOfShape aListOfShapes = anObjectToShapes[anObject];
+ TopoDS_ListOfShape::Iterator aShapesIt(aListOfShapes);
+ for (; aShapesIt.More(); aShapesIt.Next()) {
+ if (!aAlreadyHidden.Contains(aShapesIt.Value()))
+ aAlreadyHidden.Append(aShapesIt.Value());
+ }
+ aPrs->setSubShapeHidden(aAlreadyHidden);
+ aPrs->setHiddenSubShapeTransparency(aTransp);
+ }
+
+ // Remove duplicate items
+ if (aToRemove.size() > 0) {
+ myListView->removeItems(aToRemove);
+ std::set<int>::const_iterator aIntIt;
+ for (aIntIt = aToRemove.cbegin(); aIntIt != aToRemove.cend(); aIntIt++)
+ myItems.remove(*aIntIt);
+ }
if (isModified) {
updateProcessedObjects(myItems, myItemObjects);
flushRedisplay();
}
- onTransparencyChanged();
}
//********************************************************************
return false;
bool isModified = false;
- std::set<ObjectPtr> aRestoredObjects;
- for (std::set<int>::const_iterator anIt = aSelectedIds.begin(); anIt != aSelectedIds.end();
- anIt++) {
+ std::set<ModuleBase_ViewerPrsPtr> aRestored;
+ std::set<int>::const_iterator anIt;
+ for (anIt = aSelectedIds.begin(); anIt != aSelectedIds.end(); anIt++) {
ModuleBase_ViewerPrsPtr aPrs = myItems[*anIt];
- if (aRestoredObjects.find(aPrs->object()) == aRestoredObjects.end())
- aRestoredObjects.insert(aPrs->object());
- myItems.remove(*anIt);
- isModified = true;
+ if (aRestored.find(aPrs) == aRestored.end()) {
+ aRestored.insert(aPrs);
+ myItems.remove(*anIt);
+ isModified = true;
+ }
}
- if (isModified) {
- bool isRedisplayed = redisplayObjects(aRestoredObjects);
- isRedisplayed = displayHiddenObjects(aRestoredObjects, myHiddenObjects)
- || isRedisplayed;
- if (isRedisplayed) {
- flushRedisplay();
- myWorkshop->viewer()->update();
+ std::map<ObjectPtr, TopoDS_ListOfShape> anObjectToShapes;
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
+
+ std::set<ModuleBase_ViewerPrsPtr>::const_iterator aIt;
+ for (aIt = aRestored.cbegin(); aIt != aRestored.cend(); aIt++) {
+ getObjectsMapFromPrs((*aIt), anObjectToShapes, anObjectToPrs);
+ ResultGroupPtr aResGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup>((*aIt)->object());
+ if (aResGroup.get()) {
+ std::set<std::shared_ptr<ModelAPI_Object> >::iterator aGrpIt = myHiddenGroups.find(aResGroup);
+ if (aGrpIt != myHiddenGroups.end()) {
+ aResGroup->setDisplayed(true);
+ myHiddenGroups.erase(aGrpIt);
+ }
}
- // should be after flush of redisplay to have items object to be updated
- updateProcessedObjects(myItems, myItemObjects);
+ }
+ std::set<ObjectPtr> aRestoredObjects;
+ std::map<ObjectPtr, TopoDS_ListOfShape>::const_iterator aShapesIt;
+ for (aShapesIt = anObjectToShapes.begin(); aShapesIt != anObjectToShapes.end(); aShapesIt++) {
+ TopoDS_ListOfShape aShapes = aShapesIt->second;
+ aRestoredObjects.insert(aShapesIt->first);
+ Handle(ModuleBase_ResultPrs) aPrs = anObjectToPrs[aShapesIt->first];
+ TopoDS_ListOfShape aHiddenShapes = aPrs->hiddenSubShapes();
+ TopoDS_ListOfShape::Iterator aSubShapesIt(aShapes);
+ for (; aSubShapesIt.More(); aSubShapesIt.Next()) {
+ if (aHiddenShapes.Contains(aSubShapesIt.Value()))
+ aHiddenShapes.Remove(aSubShapesIt.Value());
+ }
+ aPrs->setSubShapeHidden(aHiddenShapes);
}
+ if (redisplayObjects(aRestoredObjects))
+ flushRedisplay();
myListView->removeSelectedItems();
- // Restore selection
- myListView->restoreSelection(anIndices);
- //appendSelectionInHistory();
return true;
}
return isModified;
}
-//********************************************************************
-bool XGUI_FacesPanel::displayHiddenObjects(
- const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
- std::set<std::shared_ptr<ModelAPI_Object> >& theHiddenObjects)
-{
- if (theObjects.empty())
- return false;
-
- bool isModified = false;
- static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-
- for (std::set<ObjectPtr>::const_iterator anIt = theObjects.begin(); anIt != theObjects.end();
- anIt++)
- {
- ObjectPtr anObject = *anIt;
- // if the object was hidden by this panel
- if (anObject->isDisplayed() || theHiddenObjects.find(anObject) == theHiddenObjects.end())
- continue;
- theHiddenObjects.erase(anObject);
- anObject->setDisplayed(true); // it means that the object is hidden by hide all faces
- ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
- isModified = true;
- }
- return isModified;
-}
-
-//********************************************************************
-bool XGUI_FacesPanel::hideEmptyObjects()
-{
- bool isModified = false;
- static Events_ID aDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- std::map<ObjectPtr, NCollection_List<TopoDS_Shape> > anObjectToShapes;
- std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
-
- for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
- anIt != myItems.end(); anIt++) {
- ModuleBase_ViewerPrsPtr aPrs = anIt.value();
- ObjectPtr anObject = aPrs->object();
- if (!anObject.get() || !anObject->isDisplayed())
- continue;
-
- Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
- aPrs->interactive());
- if (aResultPrs.IsNull())
- continue;
-
- if (anObjectToShapes.find(anObject) != anObjectToShapes.end())
- anObjectToShapes.at(anObject).Append(ModuleBase_Tools::getSelectedShape(aPrs));
- else {
- NCollection_List<TopoDS_Shape> aListOfShapes;
- aListOfShapes.Append(ModuleBase_Tools::getSelectedShape(aPrs));
- anObjectToShapes[anObject] = aListOfShapes;
- anObjectToPrs[anObject] = aResultPrs;
- }
- }
- for (std::map<ObjectPtr, NCollection_List<TopoDS_Shape> >::const_iterator
- anIt = anObjectToShapes.begin(); anIt != anObjectToShapes.end(); anIt++) {
- ObjectPtr anObject = anIt->first;
- if (!anObject.get() || anObjectToPrs.find(anObject) == anObjectToPrs.end())
- continue;
- Handle(ModuleBase_ResultPrs) aResultPrs = anObjectToPrs.at(anObject);
-
- if (!aResultPrs->hasSubShapeVisible(anIt->second)) {
- // erase object because it is entirely hidden
- anObject->setDisplayed(false);
- myHiddenObjects.insert(anObject);
- ModelAPI_EventCreator::get()->sendUpdated(anObject, aDispEvent);
- isModified = true;
- }
- }
- return isModified;
-}
-
//********************************************************************
void XGUI_FacesPanel::updateProcessedObjects(QMap<int, ModuleBase_ViewerPrsPtr> theItems,
std::set<ObjectPtr>& theObjects)
anIt != theItems.end(); anIt++) {
ModuleBase_ViewerPrsPtr aPrs = anIt.value();
ObjectPtr anObject = aPrs.get() ? aPrs->object() : ObjectPtr();
- if (anObject.get() && theObjects.find(anObject) != theObjects.end())
- continue;
- theObjects.insert(anObject);
+ if (anObject.get()) {
+ ResultGroupPtr aResGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(anObject);
+ if (aResGroup.get()) {
+ FeaturePtr aGroupFeature = ModelAPI_Feature::feature(aResGroup);
+ AttributeSelectionListPtr aSelectionList = aGroupFeature->selectionList("group_list");
+ for (int i = 0; i < aSelectionList->size(); i++) {
+ AttributeSelectionPtr aSelection = aSelectionList->value(i);
+ ResultPtr aRes = aSelection->context();
+ if (theObjects.find(aRes) == theObjects.end())
+ theObjects.insert(aRes);
+ }
+ }
+ else {
+ if (theObjects.find(anObject) == theObjects.end())
+ theObjects.insert(anObject);
+ }
+ }
}
}
emit closed();
}
-//********************************************************************
-bool XGUI_FacesPanel::customizeObject(const ObjectPtr& theObject,
- const AISObjectPtr& thePresentation)
-{
- if (myLastItemIndex == 0) // do nothing because there was no activity in the pane after reset
- return false;
-
- if (thePresentation.get() == NULL)
- return false;
-
- if (myItemObjects.find(theObject) == myItemObjects.end()) // not found
- return false;
-
- // if the object is displayed, the hidden faces are collected and set to the presentation
- bool isModified = false;
- NCollection_List<TopoDS_Shape> aHiddenSubShapes;
- for (QMap<int, ModuleBase_ViewerPrsPtr>::const_iterator anIt = myItems.begin();
- anIt != myItems.end(); anIt++) {
- ModuleBase_ViewerPrsPtr aPrs = anIt.value();
- if (aPrs.get() && aPrs->object() != theObject)
- continue;
- TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
- if (!aHiddenSubShapes.Contains(aShape))
- aHiddenSubShapes.Append(aShape);
- }
-
- Handle(ModuleBase_ResultPrs) aResultPrs = Handle(ModuleBase_ResultPrs)::DownCast(
- thePresentation->impl<Handle(AIS_InteractiveObject)>());
- if (aResultPrs.IsNull())
- return false;
-
- isModified = aResultPrs->setSubShapeHidden(aHiddenSubShapes);
-
- double aTransparency = !useTransparency() ? 1
- : Config_PropManager::real("Visualization", "hidden_face_transparency");
- isModified = aResultPrs->setHiddenSubShapeTransparency(aTransparency) || isModified;
-
- return isModified;
-}
-
//********************************************************************
void XGUI_FacesPanel::onDeleteItem()
{
//********************************************************************
void XGUI_FacesPanel::onTransparencyChanged()
{
- bool isModified = false;
- if (useTransparency()) {
- std::set<std::shared_ptr<ModelAPI_Object> > aHiddenObjects = myHiddenObjects;
- isModified = displayHiddenObjects(aHiddenObjects, myHiddenObjects);
+ std::map<ObjectPtr, TopoDS_ListOfShape> anObjectToShapes;
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) > anObjectToPrs;
+ QMap<int, std::shared_ptr<ModuleBase_ViewerPrs> >::const_iterator aIt;
+ for (aIt = myItems.cbegin(); aIt != myItems.cend(); aIt++) {
+ getObjectsMapFromPrs(aIt.value(), anObjectToShapes, anObjectToPrs);
}
- else
- isModified = hideEmptyObjects();
- isModified = redisplayObjects(myItemObjects) || isModified;
- if (isModified)
+ double aTransp = Config_PropManager::real("Visualization", "hidden_face_transparency");
+ std::set<ObjectPtr> aObjects;
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs)>::const_iterator aPrsIt;
+ for (aPrsIt = anObjectToPrs.cbegin(); aPrsIt != anObjectToPrs.cend(); aPrsIt++) {
+ aObjects.insert(aPrsIt->first);
+ aPrsIt->second->setHiddenSubShapeTransparency(useTransparency()? aTransp : 1);
+ }
+ if (redisplayObjects(aObjects))
flushRedisplay();
}
{
Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
// Necessary for update visibility icons in ObjectBrowser
- XGUI_ObjectsBrowser* anObjectBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
+ XGUI_ObjectsBrowser* anObjectBrowser = myWorkshop->objectBrowser();
if (anObjectBrowser)
anObjectBrowser->updateAllIndexes();
+ myWorkshop->viewer()->update();
}
#include <ModuleBase_ActionType.h>
#include <ModuleBase_Definitions.h>
#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_ResultPrs.h>
#include <SelectMgr_ListOfFilter.hxx>
+#include <TopoDS_Shape.hxx>
#include <QDockWidget>
#include <QObject>
class GeomAPI_AISObject;
-class ModuleBase_IWorkshop;
+class XGUI_Workshop;
class ModuleBase_ListView;
class QAction;
public:
/// Constructor
/// \param theParent is a parent of the property panel
- XGUI_FacesPanel(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop);
+ XGUI_FacesPanel(QWidget* theParent, XGUI_Workshop* theWorkshop);
~XGUI_FacesPanel() {}
/// Clear content of list widget
/// \param theIsActive state whether the panel should be activated or deactivated
void setActivePanel(const bool theIsActive);
- /// Returns true if transparency choice is checked
- /// \return boolean value
- bool useTransparency() const;
-
/// Returns true if the object is in internal container of hidden objects by this panel
/// \param theObject a checked object
/// \return boolean value
/// \param theEvent an event
virtual bool eventFilter(QObject* theObject, QEvent *theEvent);
- /// Hide/show faces of the object if:
- /// - face selector is active
- /// - object is mentioned in the list of selected elements
- /// If the object is displayed, all panel faces selected on it will be moved into presentation
- /// or, if redisplayed, fuction return if the object should be redisplayed or not
- /// \param theObject a customized object
- /// \param thePresentation visualized presentation of the object
- /// \return true if the presentation is customized
- bool customizeObject(const std::shared_ptr<ModelAPI_Object>& theObject,
- const std::shared_ptr<GeomAPI_AISObject>& thePresentation);
+ XGUI_Workshop* workshop() const { return myWorkshop; }
+
protected:
/// Reimplementation to emit a signal about the panel close
/// \return true if some of objects was redisplayed
static bool redisplayObjects(const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects);
- /// Display objects if the objects are in a container of hidden by this pane.
- /// \param theObjects container of objects
- /// \param theHiddenObjects hidden objects, if object is in the container, it should be removed
- /// \return true if some of objects was redisplayed
- static bool displayHiddenObjects(const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects,
- std::set<std::shared_ptr<ModelAPI_Object> >& theHiddenObjects);
-
- /// Iterates by items and hide objects where all sub-shapes are hidden
- /// \return true if some of objects was redisplayed
- bool hideEmptyObjects();
-
/// Container of objects participating in the panel, it is filled by internal container
/// \param theItems container of selected values
/// \param theObjects [out] container of objects
static void updateProcessedObjects(QMap<int, std::shared_ptr<ModuleBase_ViewerPrs> > theItems,
std::set<std::shared_ptr<ModelAPI_Object> >& theObjects);
+ /// Returns maps of shapes and presentations. If object is a body result then it returns
+ /// its ruslts. If it is a group then it returns result of shapes included into the gropup
+ /// The function doesn't clear content of input maps.
+ /// \param thePrs a selected presintation
+ /// \param theObjectsToShapes map of objects to shapes list
+ /// \param theObjectToPrs map of objects to presentations
+ void getObjectsMapFromPrs(ModuleBase_ViewerPrsPtr thePrs,
+ std::map<ObjectPtr, TopoDS_ListOfShape>& theObjectsToShapes,
+ std::map<ObjectPtr, Handle(ModuleBase_ResultPrs) >& theObjectToPrs);
+
+ /// Returns true if transparency choice is checked
+ /// \return boolean value
+ bool useTransparency() const;
+
+ double transparency() const;
+
protected slots:
/// Deletes element in list of items
void onDeleteItem();
protected:
QCheckBox* myHiddenOrTransparent; ///< if checked - transparent, else hidden
ModuleBase_ListView* myListView; ///< list control of processed faces
- ModuleBase_IWorkshop* myWorkshop; ///< workshop
+ XGUI_Workshop* myWorkshop; ///< workshop
bool myIsActive; ///< current state about the panel is active
int myLastItemIndex; ///< last index to be used in the map of items for the next added item
- QMap<int, std::shared_ptr<ModuleBase_ViewerPrs> > myItems; ///< selected face items
+ QMap<int, ModuleBase_ViewerPrsPtr> myItems; ///< selected face items
std::set<std::shared_ptr<ModelAPI_Object> > myItemObjects; ///< cached objects of myItems
std::set<std::shared_ptr<ModelAPI_Object> > myHiddenObjects; ///< hidden objects
+ std::set<std::shared_ptr<ModelAPI_Object> > myHiddenGroups; ///< hidden objects
};
#endif
\ No newline at end of file
//
#include "XGUI_InspectionPanel.h"
+#include "XGUI_Workshop.h"
#include "XGUI_SelectionMgr.h"
#include "XGUI_Selection.h"
#include "XGUI_Tools.h"
+#include "XGUI_ModuleConnector.h"
#include <ModuleBase_ViewerPrs.h>
#include <ModuleBase_Tools.h>
+#include <ModuleBase_OperationDescription.h>
+#include <ModuleBase_WidgetFactory.h>
+#include <ModuleBase_IModule.h>
+#include <ModuleBase_PageWidget.h>
+
#include <ModelAPI_ResultField.h>
#include <ModelAPI_Result.h>
#include <QTextBrowser>
#include <QResizeEvent>
#include <QSplitter>
+#include <QStackedWidget>
#include <BRepBndLib.hxx>
#include <TopoDS_Iterator.hxx>
#include <TopTools_ListOfShape.hxx>
#include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic
+
// ================ Auxiliary functions ================
#define TITLE(val) ("<b>" + (val) + "</b>")
// ================ XGUI_InspectionPanel ================
-XGUI_InspectionPanel::XGUI_InspectionPanel(QWidget* theParent, XGUI_SelectionMgr* theMgr)
+XGUI_InspectionPanel::XGUI_InspectionPanel(QWidget* theParent, XGUI_Workshop* theWorkshop)
: QDockWidget(theParent),
- mySelectionMgr(theMgr)
+ myWorkshop(theWorkshop)
{
setWindowTitle(tr("Inspection Panel"));
setObjectName(INSPECTION_PANEL);
setStyleSheet("::title { position: relative; padding-left: 5px; text-align: left center }");
- QSplitter* aSplitter = new QSplitter(Qt::Vertical, this);
+ myStackWgt = new QStackedWidget(this);
+
+ // Create shape selection page
+ QSplitter* aSplitter = new QSplitter(Qt::Vertical, myStackWgt);
// Create an internal widget
QWidget* aNameWgt = new QWidget(aSplitter);
aSizes << 10 << 140 << 10;
aSplitter->setSizes(aSizes);
- setWidget(aSplitter);
+ myShapePanelId = myStackWgt->addWidget(aSplitter);
+
+ // Create feature selection page
+ QScrollArea* aScroll = new QScrollArea(myStackWgt);
+ aScroll->setWidgetResizable(true);
+ aScroll->setFrameStyle(QFrame::NoFrame);
+
+ myFeaturePane = new ModuleBase_PageWidget(aScroll);
+ myFeatureLayout = new QGridLayout(myFeaturePane);
+ myFeatureLayout->setContentsMargins(3, 3, 3, 3);
+ aScroll->setWidget(myFeaturePane);
+ //myFeaturePane->setEnabled(false);
- connect(mySelectionMgr, SIGNAL(selectionChanged()), SLOT(onSelectionChanged()));
+ myFeaturePanelId = myStackWgt->addWidget(aScroll);
+
+ setWidget(myStackWgt);
+ connect(myWorkshop->selector(), SIGNAL(selectionChanged()), SLOT(onSelectionChanged()));
}
//********************************************************************
}
myTypeLbl->setText("");
setParamsText("");
+
+ myFeaturePane->clearPage();
}
//********************************************************************
void XGUI_InspectionPanel::onSelectionChanged()
{
+ if (!isVisible())
+ return;
+
clearContent();
- XGUI_Selection* aSelection = mySelectionMgr->selection();
- QList<ModuleBase_ViewerPrsPtr> aSelectedList =
- aSelection->getSelected(ModuleBase_ISelection::Viewer);
- QList<ModuleBase_ViewerPrsPtr> anOBSelected =
- aSelection->getSelected(ModuleBase_ISelection::Browser);
- if (!anOBSelected.isEmpty())
- ModuleBase_ISelection::appendSelected(anOBSelected, aSelectedList);
+ XGUI_Selection* aSelection = myWorkshop->selector()->selection();
+ QList<ModuleBase_ViewerPrsPtr> aSelectedList =
+ aSelection->getSelected(myWorkshop->selector()->placeOfSelection());
if (aSelectedList.count() > 0) {
ModuleBase_ViewerPrsPtr aPrs = aSelectedList.first();
std::dynamic_pointer_cast<ModelAPI_ResultField::ModelAPI_FieldStep>(aPrs->object());
if (aStep)
return;
- TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
- if (aShape.IsNull()) {
- ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPrs->object());
- if (aRes.get()) {
- GeomShapePtr aShpPtr = aRes->shape();
- if (aShpPtr.get()) {
- aShape = aShpPtr->impl<TopoDS_Shape>();
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aPrs->object());
+ if (aFeature.get()) {
+ myStackWgt->setCurrentIndex(myFeaturePanelId);
+ buildFeaturePane(aFeature);
+ }
+ else {
+ myStackWgt->setCurrentIndex(myShapePanelId);
+ TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(aPrs);
+ if (aShape.IsNull()) {
+ ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aPrs->object());
+ if (aRes.get()) {
+ GeomShapePtr aShpPtr = aRes->shape();
+ if (aShpPtr.get()) {
+ aShape = aShpPtr->impl<TopoDS_Shape>();
+ }
}
}
+ if (aShape.IsNull())
+ return;
+ GeomShapePtr aShapePtr(new GeomAPI_Shape());
+ aShapePtr->setImpl(new TopoDS_Shape(aShape));
+
+ ModuleBase_ViewerPrsPtr aPrsCopy(new ModuleBase_ViewerPrs(aPrs->object(), aShapePtr));
+ setName(XGUI_Tools::generateName(aPrsCopy));
+ setShapeContent(aShape);
+ setShapeParams(aShape);
}
- if (aShape.IsNull())
- return;
- GeomShapePtr aShapePtr(new GeomAPI_Shape());
- aShapePtr->setImpl(new TopoDS_Shape(aShape));
-
- ModuleBase_ViewerPrsPtr aPrsCopy(new ModuleBase_ViewerPrs(aPrs->object(), aShapePtr));
- setName(XGUI_Tools::generateName(aPrsCopy));
- setShapeContent(aShape);
- setShapeParams(aShape);
}
}
appendPointToParameters(tr("Maximal corner"), aMaxPoint, aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setPlaneType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Pln>& thePlane)
{
setParamsText(aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setSphereType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Sphere>& theSphere)
{
setParamsText(aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setCylinderType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Cylinder>& theCyl)
{
setParamsText(aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setConeType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Cone>& theCone)
{
setParamsText(aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setTorusType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Torus>& theTorus)
{
setParamsText(aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setBoxType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Box>& theBox)
{
setParamsText(aParams);
}
+//********************************************************************
void XGUI_InspectionPanel::setRotatedBoxType(const QString& theTitle,
const std::shared_ptr<GeomAPI_Box>& theBox)
{
}
+//********************************************************************
void XGUI_InspectionPanel::setParamsText(const QString& theText)
{
myTypeParams->setText(theText);
}
+
+//********************************************************************
+void XGUI_InspectionPanel::buildFeaturePane(const FeaturePtr& theFeature)
+{
+ std::string aXmlCfg, aDescription;
+ myWorkshop->module()->getXMLRepresentation(theFeature->getKind(), aXmlCfg, aDescription);
+ if (!aXmlCfg.empty()) {
+ QList<ModuleBase_ModelWidget*> aWidgets;
+ if (!myWorkshop->module()->createWidgets(theFeature, aXmlCfg.c_str(), aWidgets)) {
+ ModuleBase_WidgetFactory aFactory(aXmlCfg, myWorkshop->moduleConnector());
+ aFactory.createWidget(myFeaturePane);
+ aWidgets = aFactory.getModelWidgets();
+ }
+ foreach(ModuleBase_ModelWidget* aWgt, aWidgets) {
+ if (aWgt->isInformative()) {
+ aWgt->setFeature(theFeature, false, false);
+ aWgt->setReadOnly(true);
+ aWgt->setEditingMode(true);
+ aWgt->restoreValue();
+ aWgt->showInformativePage();
+ }
+ else {
+ aWgt->setFeature(theFeature, false, false);
+ aWgt->setEditingMode(true);
+ aWgt->hide();
+ }
+ }
+ }
+}
+
+void XGUI_InspectionPanel::showEvent(QShowEvent* theEvent)
+{
+ QDockWidget::showEvent(theEvent);
+ onSelectionChanged();
+}
#include "XGUI.h"
+#include <ModelAPI_Feature.h>
+
#include <QDockWidget>
#include <memory>
-class XGUI_SelectionMgr;
+class XGUI_Workshop;
class QLineEdit;
class QTableWidget;
class QLabel;
class QTextBrowser;
class QVBoxLayout;
class QResizeEvent;
+class QStackedWidget;
+class QGridLayout;
class TopoDS_Shape;
class GeomAPI_Cone;
class GeomAPI_Torus;
class GeomAPI_Box;
+class ModuleBase_PageWidget;
/// Internal name of property panel widget
const static char* INSPECTION_PANEL = "inspection_panel_dock";
/// Constructor
/// \param theParent is a parent of the property panel
/// \param theMgr operation manager
- XGUI_InspectionPanel(QWidget* theParent, XGUI_SelectionMgr* theMgr);
+ XGUI_InspectionPanel(QWidget* theParent, XGUI_Workshop* theWorkshop);
// Destructor
virtual ~XGUI_InspectionPanel();
+protected:
+ virtual void showEvent(QShowEvent* theEvent);
private slots:
/// A slot to react on selection changed
/// \param theBox the box
void setRotatedBoxType(const QString& theTitle, const std::shared_ptr<GeomAPI_Box>& theBox);
-
/// Set text into parameters area
/// \param theText the text
void setParamsText(const QString& theText);
+ /// Fills Feature panel with controls specific to the given feature
+ /// \param theFeature the selected feature
+ void buildFeaturePane(const FeaturePtr& theFeature);
+
private:
- XGUI_SelectionMgr* mySelectionMgr; //> selection manager
-
- QLineEdit* myNameEdt; //> Name field
- QTableWidget* mySubShapesTab; //> table of sub-shapes
- QLabel* myTypeLbl; //> label of a type
- QTextBrowser* myTypeParams; //> parameters area
- QVBoxLayout* myMainLayout; //> main layout
- //QWidget* myMainWidget; //> main widget
+ XGUI_Workshop* myWorkshop; //> selection manager
+
+ QLineEdit* myNameEdt; ///> Name field
+ QTableWidget* mySubShapesTab; ///> table of sub-shapes
+ QLabel* myTypeLbl; ///> label of a type
+ QTextBrowser* myTypeParams; ///> parameters area
+ QVBoxLayout* myMainLayout; ///> main layout
+ ModuleBase_PageWidget* myFeaturePane; ///> Content of feature property panel
+ QGridLayout* myFeatureLayout; ///> Layout of feature panel
+ QStackedWidget* myStackWgt; ///> base widget of the panel
+ int myShapePanelId;
+ int myFeaturePanelId;
};
#endif
\ No newline at end of file
myWorkshop->selector()->clearSelection();
aBrowser->treeView()->clearSelection();
} else {
- aDisp->setSelected(theValues);
- // Synchronise the selection with Object browser
- QObjectPtrList anObjects;
- foreach(ModuleBase_ViewerPrsPtr aVal, theValues) {
- anObjects.append(aVal->object());
- }
- aBrowser->setObjectsSelected(anObjects);
+ myWorkshop->selector()->setSelected(theValues);
}
}
{
Handle(AIS_InteractiveObject) anIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
myWorkshop->selectionActivate()->activate(anIO, false);
-}
\ No newline at end of file
+}
+
+
+void XGUI_ModuleConnector::undo()
+{
+ myWorkshop->onUndo();
+}
+
+void XGUI_ModuleConnector::setCancelEnabled(bool toEnable)
+{
+ XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
+ QAction* aAbortAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll);
+ QAction* aAbortAllAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
+ if (aAbortAction) {
+ aAbortAction->setEnabled(toEnable);
+ }
+ if (aAbortAllAction) {
+ aAbortAllAction->setEnabled(toEnable);
+ }
+}
+
+bool XGUI_ModuleConnector::isCancelEnabled() const
+{
+ XGUI_ActionsMgr* anActionsMgr = workshop()->actionsMgr();
+ QAction* aAbortAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::AbortAll);
+ QAction* aAbortAllAction = anActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
+ bool isEnabled = false;
+ if (aAbortAction) {
+ isEnabled = true;
+ }
+ if (aAbortAllAction) {
+ isEnabled &= true;
+ }
+ return isEnabled;
+}
//! \param theAIS the object which has to be activated
virtual void applyCurrentSelectionModes(const AISObjectPtr& theAIS);
+ //! Undo last command
+ virtual void undo();
+
+ //! Set enabled state of cancel button in property panel
+ virtual void setCancelEnabled(bool toEnable);
+
+ //! Returns current state of cancel button
+ virtual bool isCancelEnabled() const;
+
private:
QObjectPtrList activeObjects(const QObjectPtrList& theObjList) const;
}
}
if (aResultOp) {
- bool isModified = aCurrentOperation->isModified();
- aResultOp->setIsModified(aResultOp->isModified() || isModified);
+ //bool isModified = aCurrentOperation->isModified();
+ //aResultOp->setIsModified(aResultOp->isModified() || isModified);
resumeOperation(aResultOp);
onValidateOperation();
}
/// processing delete by workshop
XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
- bool isToDeleteObject = false;
+ bool isToDeleteObject = true;
XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
if (theObject == aBrowser->treeView()) {
//**************************************************************
void XGUI_SelectionMgr::onObjectBrowserSelection()
{
+ myLastSelectionPlace = ModuleBase_ISelection::Browser;
QList<ModuleBase_ViewerPrsPtr> aSelectedPrs =
myWorkshop->selector()->selection()->getSelected(ModuleBase_ISelection::Browser);
XGUI_Displayer* aDisplayer = myWorkshop->displayer();
//**************************************************************
void XGUI_SelectionMgr::onViewerSelection()
{
+ myLastSelectionPlace = ModuleBase_ISelection::Viewer;
QList<ModuleBase_ViewerPrsPtr> aValues;
Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
if (!aContext.IsNull())
return mySelection;
}
+ ModuleBase_ISelection::SelectionPlace placeOfSelection() const {
+ return myLastSelectionPlace;
+ }
+
//! Connects the manager to all viewers accessible by Workshop
void connectViewers();
/// Current selection object
XGUI_Selection* mySelection;
+
+ ModuleBase_ISelection::SelectionPlace myLastSelectionPlace;
};
#endif
if (aContext.get()) {
GeomShapePtr aSubShape(new GeomAPI_Shape());
TopoDS_Shape aShape = ModuleBase_Tools::getSelectedShape(thePrs);
- aSubShape->setImpl(new TopoDS_Shape(aShape));
- if (!aSubShape->isEqual(aContext)) {
- QString aTypeName;
- switch (aShape.ShapeType()) {
- case TopAbs_COMPOUND:
- aTypeName = "compound";
- break;
- case TopAbs_COMPSOLID:
- aTypeName = "compsolid";
- break;
- case TopAbs_SOLID:
- aTypeName = "solid";
- break;
- case TopAbs_SHELL:
- aTypeName = "shell";
- break;
- case TopAbs_FACE:
- aTypeName = "face";
- break;
- case TopAbs_WIRE:
- aTypeName = "wire";
- break;
- case TopAbs_EDGE:
- aTypeName = "edge";
- break;
- case TopAbs_VERTEX:
- aTypeName = "vertex";
- break;
- case TopAbs_SHAPE:
- aTypeName = "shape";
- break;
+ if (!aShape.IsNull()) {
+ aSubShape->setImpl(new TopoDS_Shape(aShape));
+ if (!aSubShape->isEqual(aContext)) {
+ QString aTypeName;
+ switch (aShape.ShapeType()) {
+ case TopAbs_COMPOUND:
+ aTypeName = "compound";
+ break;
+ case TopAbs_COMPSOLID:
+ aTypeName = "compsolid";
+ break;
+ case TopAbs_SOLID:
+ aTypeName = "solid";
+ break;
+ case TopAbs_SHELL:
+ aTypeName = "shell";
+ break;
+ case TopAbs_FACE:
+ aTypeName = "face";
+ break;
+ case TopAbs_WIRE:
+ aTypeName = "wire";
+ break;
+ case TopAbs_EDGE:
+ aTypeName = "edge";
+ break;
+ case TopAbs_VERTEX:
+ aTypeName = "vertex";
+ break;
+ case TopAbs_SHAPE:
+ aTypeName = "shape";
+ break;
+ }
+ int aId = GeomAlgoAPI_CompoundBuilder::id(aContext, aSubShape);
+ aName += QString("/%1_%2").arg(aTypeName).arg(aId);
}
- int aId = GeomAlgoAPI_CompoundBuilder::id(aContext, aSubShape);
- aName += QString("/%1_%2").arg(aTypeName).arg(aId);
}
}
return aName;
#include "XGUI_Tools.h"
#include "XGUI_ViewerProxy.h"
#include "XGUI_WorkshopListener.h"
-#include <XGUI_CustomPrs.h>
#include <XGUI_HistoryMenu.h>
#include <XGUI_QtEvents.h>
#include <XGUI_DataModel.h>
#include <ModelAPI_AttributeDocRef.h>
#include <ModelAPI_AttributeIntArray.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeString.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Events.h>
#include <ModelAPI_Feature.h>
#include <Events_InfoMessage.h>
#include <Events_LongOp.h>
+#include <ExchangePlugin_ExportPart.h>
+#include <ExchangePlugin_ImportPart.h>
+
#include <GeomAPI_Pnt.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <ModuleBase_IModule.h>
#include <ModuleBase_IViewer.h>
#include <ModuleBase_Tools.h>
#include <ModuleBase_WidgetFactory.h>
#include <ModuleBase_OperationFeature.h>
-#include <ModuleBase_OperationAction.h>
#include <ModuleBase_PagedContainer.h>
#include <ModuleBase_WidgetValidated.h>
#include <ModuleBase_ModelWidget.h>
//#define DEBUG_WITH_MESSAGE_REPORT
QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
+QString XGUI_Workshop::MOVE_TO_END_SPLIT_COMMAND = QObject::tr("Move to the end and split");
//#define DEBUG_DELETE
//#define DEBUG_FEATURE_NAME
static QString MyExtension(".cadbld");
#endif
+static QString MyImportPartFilter(QObject::tr("Part files (*.shaperpart);;All files (*.*)"));
+
//******************************************************
XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
connect(myEventsListener, SIGNAL(errorOccurred(std::shared_ptr<Events_InfoMessage>)),
myErrorDlg, SLOT(addError(std::shared_ptr<Events_InfoMessage>)));
- //Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
- // Config_Prop::Color, "225,225,225");
-
- Config_PropManager::registerProp("Visualization", "result_body_color", "Result color",
- Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR());
- Config_PropManager::registerProp("Visualization", "result_group_color", "Group color",
- Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR());
- Config_PropManager::registerProp("Visualization", "result_construction_color",
- "Construction color",
- Config_Prop::Color,
- ModelAPI_ResultConstruction::DEFAULT_COLOR());
- Config_PropManager::registerProp("Visualization", "result_part_color", "Part color",
- Config_Prop::Color, ModelAPI_ResultPart::DEFAULT_COLOR());
- Config_PropManager::registerProp("Visualization", "result_field_color", "Field color",
- Config_Prop::Color, ModelAPI_ResultField::DEFAULT_COLOR());
+ Config_PropManager::registerProp("Visualization", "selection_color", "Selection color",
+ Config_Prop::Color, "255,255,255");
if (ModuleBase_Preferences::resourceMgr()->booleanValue("Viewer", "face-selection", true))
myViewerSelMode.append(TopAbs_FACE);
// Calling of loadCustomProps before activating module is required
// by Config_PropManger to restore user-defined path to plugins
ModuleBase_Preferences::loadCustomProps();
+ std::vector<int> aColor;
+ try {
+ aColor = Config_PropManager::color("Visualization", "selection_color");
+ }
+ catch (...) {
+ }
+ if (aColor.size() == 3)
+ myDisplayer->setSelectionColor(aColor);
+
createModule();
#ifndef HAVE_SALOME
connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onOpen()));
salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE");
+ aAction = salomeConnector()->addDesktopCommand("EXPORT_PART_CMD", tr("Export part..."),
+ tr("Export a part of the current document into a file"),
+ QIcon(), QKeySequence(),
+ false, "MEN_DESK_FILE");
+ connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onExportPart()));
+
+ aAction = salomeConnector()->addDesktopCommand("IMPORT_PART_CMD", tr("Import part..."),
+ tr("Import structure of a part"),
+ QIcon(), QKeySequence(),
+ false, "MEN_DESK_FILE");
+ connect(aAction, SIGNAL(triggered(bool)), this, SLOT(onImportPart()));
+ salomeConnector()->addDesktopMenuSeparator("MEN_DESK_FILE");
+
#else
// File commands group
AppElements_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage();
if (!aFOperation)
return;
- showPanel(myPropertyPanel);
myPropertyPanel->cleanContent();
QList<ModuleBase_ModelWidget*> aWidgets;
- if (!module()->createWidgets(theOperation, aWidgets)) {
- QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
+ QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
+ if (!module()->createWidgets(aFOperation->feature(), aXmlRepr, aWidgets)) {
ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myModuleConnector);
aFactory.createWidget(myPropertyPanel->contentWidget());
aWidgets = aFactory.getModelWidgets();
#endif
myErrorMgr->setPropertyPanel(myPropertyPanel);
+ if (Config_PropManager::boolean("Windows", "use_hide_faces_panel")) {
+ theOperation->setHideFacesVisible(myFacesPanel->isVisible());
+ if (aFeatureInfo.get() && aFeatureInfo->isHideFacesPanel() && !myFacesPanel->isVisible())
+ myFacesPanel->show();
+ }
+ showPanel(myPropertyPanel);
}
//******************************************************
}
}
activateObjectsSelection(anObjects);
+
+ if (Config_PropManager::boolean("Windows", "use_hide_faces_panel")) {
+ if (!theOperation->isHideFacesVisible())
+ myFacesPanel->hide();
+ }
}
//******************************************************
QMdiSubWindow* aWnd = myMainWindow->viewer()->createView();
aWnd->showMaximized();
updateCommandStatus();
+ PyConsole_Console* aConsole = myMainWindow->pythonConsole();
+ connect(aConsole, SIGNAL(scriptLoaded()), SLOT(updateCommandStatus()));
#endif
myContextMenuMgr->connectViewer();
QApplication::restoreOverrideCursor();
ModuleBase_Preferences::editPreferences(aModif);
if (aModif.size() > 0) {
QString aSection;
- foreach (ModuleBase_Pref aPref, aModif)
- {
+ foreach (ModuleBase_Pref aPref, aModif) {
aSection = aPref.first;
if (aSection == ModuleBase_Preferences::VIEWER_SECTION) {
myMainWindow->viewer()->updateFromResources();
myMainWindow->menuObject()->updateFromResources();
}
}
+ std::vector<int> aColor;
+ try {
+ aColor = Config_PropManager::color("Visualization", "selection_color");
+ }
+ catch (...) {
+ }
+ if (aColor.size() == 3)
+ displayer()->setSelectionColor(aColor);
+
displayer()->redisplayObjects();
}
}
else
aMgr->redo();
- if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
+ if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND ||
+ QString((*aIt).c_str()) == MOVE_TO_END_SPLIT_COMMAND)
myObjectBrowser->rebuildDataTree();
}
operationMgr()->updateApplyOfOperations();
myDisplayer->updateViewer();
}
+//******************************************************
+void XGUI_Workshop::onImportPart()
+{
+ if (abortAllOperations()) {
+ ModuleBase_OperationFeature* anImportPartOp = dynamic_cast<ModuleBase_OperationFeature*>(
+ module()->createOperation(ExchangePlugin_ImportPart::ID()));
+ operationMgr()->startOperation(anImportPartOp);
+ }
+}
+
+//******************************************************
+void XGUI_Workshop::onExportPart()
+{
+ if (abortAllOperations()) {
+ ModuleBase_OperationFeature* anExportPartOp = dynamic_cast<ModuleBase_OperationFeature*>(
+ module()->createOperation(ExchangePlugin_ExportPart::ID()));
+ operationMgr()->startOperation(anExportPartOp);
+ }
+}
+
//******************************************************
ModuleBase_IModule* XGUI_Workshop::loadModule(const QString& theModule)
{
hidePanel(myPropertyPanel); ///<! Invisible by default
- myFacesPanel = new XGUI_FacesPanel(aDesktop, myModuleConnector);
+ myFacesPanel = new XGUI_FacesPanel(aDesktop, this);
myActiveControlMgr->addSelector(new XGUI_FacesPanelSelector(myFacesPanel));
myFacesPanel->setAllowedAreas(Qt::LeftDockWidgetArea |
Qt::RightDockWidgetArea |
Qt::BottomDockWidgetArea);
connect(myFacesPanel, SIGNAL(closed()), myFacesPanel, SLOT(onClosed()));
- myInspectionPanel = new XGUI_InspectionPanel(aDesktop, mySelector);
+ myInspectionPanel = new XGUI_InspectionPanel(aDesktop, this);
myInspectionPanel->setAllowedAreas(Qt::LeftDockWidgetArea |
Qt::RightDockWidgetArea);
aDesktop->addDockWidget(Qt::RightDockWidgetArea, myInspectionPanel);
// in order to operation manager could process key events of the panel.
// otherwise they are ignored. It happens only if the same(activateWindow) is
// not happened by property panel activation(e.g. resume operation of Sketch)
- ModuleBase_Tools::setFocus(theDockWidget, "XGUI_Workshop::showPanel()");
+ //ModuleBase_Tools::setFocus(theDockWidget, "XGUI_Workshop::showPanel()");
}
//******************************************************
deleteObjects();
else if (theId == "CLEAN_HISTORY_CMD")
cleanHistory();
- else if (theId == "MOVE_CMD")
- moveObjects();
+ else if (theId == "MOVE_CMD" || theId == "MOVE_SPLIT_CMD")
+ moveObjects(theId == "MOVE_SPLIT_CMD");
else if (theId == "COLOR_CMD")
changeColor(aObjects);
else if (theId == "DEFLECTION_CMD")
// allow the module to delete objects, do nothing if it has succeed
if (aModule->deleteObjects()) {
updateCommandStatus();
+ myDisplayer->updateViewer();
return;
}
bool aDone = false;
QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text() + " %1";
aDescription = aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
- ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
+ ModuleBase_Operation* anOpAction = new ModuleBase_Operation(aDescription, module());
operationMgr()->startOperation(anOpAction);
// 1. start operation
aDescription += "by deleting of " +
aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
- ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
+ ModuleBase_Operation* anOpAction = new ModuleBase_Operation(aDescription, module());
operationMgr()->startOperation(anOpAction);
// WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree
DocumentPtr aDoc = theF1->document();
return aDoc->index(theF1) < aDoc->index(theF2);
}
-void XGUI_Workshop::moveObjects()
+void XGUI_Workshop::moveObjects(const bool theSplit)
{
if (!abortAllOperations())
return;
if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
return;
- QString anActionId = "MOVE_CMD";
+ QString anActionId = theSplit ? "MOVE_CMD" : "MOVE_SPLIT_CMD";
QString aDescription = contextMenuMgr()->action(anActionId)->text();
aMgr->startOperation(aDescription.toStdString());
if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
continue;
- anActiveDocument->moveFeature(aFeature, aCurrentFeature);
+ anActiveDocument->moveFeature(aFeature, aCurrentFeature, theSplit);
aCurrentFeature = anActiveDocument->currentFeature(true);
}
aMgr->finishOperation();
updateCommandStatus();
+ myViewerProxy->update();
}
//**************************************************************
aColorAttr->setValue(1, theColor[1]);
aColorAttr->setValue(2, theColor[2]);
}
- static const Events_ID kRedisplayEvent =
- Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, kRedisplayEvent);
+}
+
+//**************************************************************
+void getDefaultColor(ObjectPtr theObject, const bool isEmptyColorValid,
+ std::vector<int>& theColor)
+{
+ theColor.clear();
+ // get default color from the preferences manager for the given result
+ if (theColor.empty()) {
+ std::string aSection, aName, aDefault;
+ theObject->colorConfigInfo(aSection, aName, aDefault);
+ if (!aSection.empty() && !aName.empty()) {
+ theColor = Config_PropManager::color(aSection, aName);
+ }
+ }
+ if (!isEmptyColorValid && theColor.empty()) {
+ // all AIS objects, where the color is not set, are in black.
+ // The color should be defined in XML or set in the attribute
+ theColor = Config_PropManager::color("Visualization", "object_default_color");
+ Events_InfoMessage("XGUI_CustomPrs",
+ "A default color is not defined in the preferences for this kind of result").send();
+ }
}
//**************************************************************
foreach(ObjectPtr anObject, theObjects) {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
if (aResult.get()) {
- XGUI_CustomPrs::getResultColor(aResult, aColor);
+ ModelAPI_Tools::getColor(aResult, aColor);
+ if (aColor.empty())
+ getDefaultColor(aResult, false, aColor);
}
else {
// TODO: remove the obtaining a color from the AIS object
setColor(aResult, !isRandomColor ? aColorResult : aDlg->getRandomColor());
}
}
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
aMgr->finishOperation();
updateCommandStatus();
+ myViewerProxy->update();
}
//**************************************************************
return;
AttributeDoublePtr aDeflectionAttr = theResult->data()->real(ModelAPI_Result::DEFLECTION_ID());
- if (aDeflectionAttr.get() != NULL)
+ if (aDeflectionAttr.get() != NULL) {
aDeflectionAttr->setValue(theDeflection);
- static const Events_ID kRedisplayEvent =
- Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, kRedisplayEvent);
+ }
}
//**************************************************************
return;
AttributeDoublePtr anAttribute = theResult->data()->real(ModelAPI_Result::TRANSPARENCY_ID());
- if (anAttribute.get() != NULL)
+ if (anAttribute.get() != NULL) {
anAttribute->setValue(theTransparency);
- static const Events_ID kRedisplayEvent =
- Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- ModelAPI_EventCreator::get()->sendUpdated(theResult, kRedisplayEvent);
+ }
}
//**************************************************************
if (aBodyResult.get() != NULL) { // change property for all sub-solids
std::list<ResultPtr> allRes;
ModelAPI_Tools::allSubs(aBodyResult, allRes);
- for(std::list<ResultPtr>::iterator aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
+ std::list<ResultPtr>::iterator aRes;
+ for(aRes = allRes.begin(); aRes != allRes.end(); aRes++) {
setTransparency(*aRes, theTransparency);
}
}
}
}
+//**************************************************************
+double getDefaultDeflection(const ObjectPtr& theObject)
+{
+ double aDeflection = -1;
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+ if (aResult.get()) {
+ bool isConstruction = false;
+
+ std::string aResultGroup = aResult->groupName();
+ if (aResultGroup == ModelAPI_ResultConstruction::group())
+ isConstruction = true;
+ else if (aResultGroup == ModelAPI_ResultBody::group()) {
+ GeomShapePtr aGeomShape = aResult->shape();
+ if (aGeomShape.get()) {
+ // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
+ // correction of deviation for them should not influence to the application performance
+ GeomAPI_ShapeExplorer anExp(aGeomShape, GeomAPI_Shape::FACE);
+ isConstruction = !anExp.more();
+ }
+ }
+ if (isConstruction)
+ aDeflection = Config_PropManager::real("Visualization", "construction_deflection");
+ else
+ aDeflection = Config_PropManager::real("Visualization", "body_deflection");
+ }
+ return aDeflection;
+}
+
//**************************************************************
void XGUI_Workshop::changeDeflection(const QObjectPtrList& theObjects)
{
foreach(ObjectPtr anObject, theObjects) {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
if (aResult.get()) {
- aDeflection = XGUI_CustomPrs::getResultDeflection(aResult);
+ aDeflection = ModelAPI_Tools::getDeflection(aResult);
+ if (aDeflection < 0)
+ aDeflection = getDefaultDeflection(aResult);
}
else {
// TODO: remove the obtaining a property from the AIS object
setDeflection(aResult, aDeflection);
}
}
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
aMgr->finishOperation();
updateCommandStatus();
}
+//**************************************************************
+double getDefaultTransparency(const ResultPtr& theResult)
+{
+ return Config_PropManager::integer("Visualization", "shaper_default_transparency") / 100.;
+}
+
//**************************************************************
void XGUI_Workshop::changeTransparency(const QObjectPtrList& theObjects)
{
foreach(ObjectPtr anObject, theObjects) {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(anObject);
if (aResult.get()) {
- aCurrentValue = XGUI_CustomPrs::getResultTransparency(aResult);
+ aCurrentValue = ModelAPI_Tools::getTransparency(aResult);
+ if (aCurrentValue < 0)
+ aCurrentValue = getDefaultTransparency(aResult);
}
if (aCurrentValue > 0)
break;
QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
setTransparency(aTransparencyWidget->getValue(), anObjects);
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ static const Events_ID kRedisplayEvent =
+ Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ Events_Loop::loop()->flush(kRedisplayEvent);
+
+ myViewerProxy->update();
}
int aSize = theDoc->numInternalFeatures();
for (int i = 0; i < aSize; i++) {
aFeature = theDoc->internalFeature(i);
+ if (!aFeature.get())
+ continue;
const std::list<ResultPtr>& aResults = aFeature->results();
std::list<ResultPtr>::const_iterator aIt;
aFeature->setDisplayed(false);
bool canMoveFeature();
/// Move selected features to be after the current feature
- void moveObjects();
+ void moveObjects(const bool theSplit);
/// Returns true if the object can be shaded. If the object is a compsolid result, the method
/// checks subobjects of the result
/// A constant string used for "Move to end" command definition
/// It is used for specific processing of Undo/Redo for this command.
static QString MOVE_TO_END_COMMAND;
+ /// A constant string used for "Move to end and split" command definition
+ /// It is used for specific processing of Undo/Redo for this command.
+ static QString MOVE_TO_END_SPLIT_COMMAND;
/// Closes all in the current session and load the directory
/// \param theDirectory a path to directory
/// Create a new document
void onNew();
+ /// Import part structure from a file
+ void onImportPart();
+
+ /// Export features to a file
+ void onExportPart();
+
#ifndef HAVE_SALOME
/// Exit application
void onExit();
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_VISUAL_ATTRIBUTES));
aLoop->registerListener(this, Events_LongOp::eventID());
aLoop->registerListener(this, Events_Loop::eventByName(EVENT_PLUGIN_LOADED));
// Redisplay feature
else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)) {
std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
- std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
onFeatureRedisplayMsg(aUpdMsg);
+ }
+ else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_VISUAL_ATTRIBUTES)) {
+ std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
+ std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+ std::set<ObjectPtr> aObjList = aUpdMsg->objects();
+ std::set<ObjectPtr>::const_iterator aIt;
+ std::list<ResultPtr>::const_iterator aResIt;
+ XGUI_Displayer* aDisplayer = workshop()->displayer();
+ AISObjectPtr aAIS;
+ for (aIt = aObjList.begin(); aIt != aObjList.end(); ++aIt) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*aIt);
+ if (aFeature) {
+ aAIS = aDisplayer->getAISObject(aFeature);
+ if (aAIS.get())
+ workshop()->module()->customizePresentation(aFeature, aAIS);
+
+ std::list<ResultPtr> aResults = aFeature->results();
+ for (aResIt = aResults.begin(); aResIt != aResults.end(); ++aResIt) {
+ aAIS = aDisplayer->getAISObject(*aResIt);
+ if (aAIS.get())
+ workshop()->module()->customizePresentation(*aResIt, aAIS);
+ }
+ }
+ }
} else if (theMessage->eventID() == Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION)) {
std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
//if (aHiddenObjects.size() > 0)
// myWorkshop->module()->processHiddenObject(aHiddenObjects);
- bool isCustomized = customizeCurrentObject(anObjects, aRedisplayed);
+ bool isCustomized = customizeFeature(anObjects, aRedisplayed);
if (aRedisplayed || isCustomized) {
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
}
}
- bool isCustomized = customizeCurrentObject(anObjects, aDisplayed);
+ bool isCustomized = customizeFeature(anObjects, aDisplayed);
//if (myObjectBrowser)
// myObjectBrowser->processEvent(theMsg);
return aDisplayer->display(theObj, false);
}
-bool XGUI_WorkshopListener::customizeCurrentObject(const std::set<ObjectPtr>& theObjects,
+bool XGUI_WorkshopListener::customizeFeature(const std::set<ObjectPtr>& theObjects,
bool theForceRedisplay)
{
XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
// the feature is hidden, but arguments of the feature are modified
// e.g. extrusion is hidden(h=0) but sketch is chosen
if (theForceRedisplay || theObjects.find(aCurrentFeature) != theObjects.end()) {
- aCustomized = myWorkshop->module()->customizeObject(aCurrentFeature,
+ aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
ModuleBase_IModule::CustomizeArguments, false) || aCustomized;
- aCustomized = myWorkshop->module()->customizeObject(aCurrentFeature,
+ aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
ModuleBase_IModule::CustomizeResults, false) || aCustomized;
- aCustomized = myWorkshop->module()->customizeObject(aCurrentFeature,
+ aCustomized = myWorkshop->module()->customizeFeature(aCurrentFeature,
ModuleBase_IModule::CustomizeHighlightedObjects, false) || aCustomized;
}
}
/// if forced redisplay is false
/// \param theForceRedisplay a flag to customize object even always
/// \return true if the object is modified
- bool customizeCurrentObject(const std::set<ObjectPtr>& theObjects, bool theForceRedisplay);
+ bool customizeFeature(const std::set<ObjectPtr>& theObjects, bool theForceRedisplay);
/// Returns the workshop
XGUI_Workshop* workshop() const;
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>QObject</name>
+ <message>
+ <source>Warning</source>
+ <translation>Attention</translation>
+ </message>
+ <message>
+ <source>Name %2 already exists in %1.</source>
+ <translation>Le nom %2 existe déjà dans %1.</translation>
+ </message>
+ <message>
+ <source>Move to the end</source>
+ <translation>Aller à la fin</translation>
+ </message>
+ <message>
+ <source>Move to the end and split</source>
+ <translation>Aller à la fin et diviser</translation>
+ </message>
+ <message>
+ <source>SHAPER files (*.shaper *.cadbld)</source>
+ <translation>Fichiers SHAPER (*.shaper *.cadbld)</translation>
+ </message>
+ <message>
+ <source>SHAPER files (*.shaper)</source>
+ <translation>Fichiers SHAPER (*.shaper)</translation>
+ </message>
+ <message>
+ <source>CAD Builder files (*.cadbld);;All files (*.*)</source>
+ <translation>Fichiers CAD Builder (*.cadbld);;Tous les fichiers (*. *)</translation>
+ </message>
+ <message>
+ <source>CAD Builder files (*.cadbld)</source>
+ <translation>Fichiers CAD Builder (*.cadbld)</translation>
+ </message>
+ <message>
+ <source>Abort operation</source>
+ <translation>Abandonner l'opération</translation>
+ </message>
+ <message>
+ <source>Validate operation</source>
+ <translation>Valider l'opération</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ActionsMgr</name>
+ <message>
+ <source>Shortcut %1 is already defined. Ignore.</source>
+ <translation>Le raccourci %1 est déjà défini. Ignorer.</translation>
+ </message>
+ <message>
+ <source>Apply</source>
+ <translation>Appliquer</translation>
+ </message>
+ <message>
+ <source>Apply and continue</source>
+ <translation>Appliquer et continuer</translation>
+ </message>
+ <message>
+ <source>Cancel</source>
+ <translation>Annuler</translation>
+ </message>
+ <message>
+ <source>Help</source>
+ <translation>Aide</translation>
+ </message>
+ <message>
+ <source>See preview</source>
+ <translation>Voir l'aperçu</translation>
+ </message>
+ <message>
+ <source>Compute preview</source>
+ <translation>Calculer l'aperçu avant impression</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ColorDialog</name>
+ <message>
+ <source>Color</source>
+ <translation>Couleur</translation>
+ </message>
+ <message>
+ <source>Random</source>
+ <translation>Aléatoire</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ContextMenuMgr</name>
+ <message>
+ <source>Delete</source>
+ <translation>Effacer</translation>
+ </message>
+ <message>
+ <source>Rename</source>
+ <translation>Renommer</translation>
+ </message>
+ <message>
+ <source>Clean history</source>
+ <translation>Vider l’historique</translation>
+ </message>
+ <message>
+ <source>Color...</source>
+ <translation>Couleur...</translation>
+ </message>
+ <message>
+ <source>Deflection...</source>
+ <translation>Déviation...</translation>
+ </message>
+ <message>
+ <source>Transparency...</source>
+ <translation>Transparence...</translation>
+ </message>
+ <message>
+ <source>Show</source>
+ <translation>Afficher</translation>
+ </message>
+ <message>
+ <source>Show only</source>
+ <translation>Montrer seulement</translation>
+ </message>
+ <message>
+ <source>Hide</source>
+ <translation>Cacher</translation>
+ </message>
+ <message>
+ <source>Hide all</source>
+ <translation>Cacher tout</translation>
+ </message>
+ <message>
+ <source>Shading</source>
+ <translation>Ombrage</translation>
+ </message>
+ <message>
+ <source>Wireframe</source>
+ <translation>Fil de fer</translation>
+ </message>
+ <message>
+ <source>Vertices</source>
+ <translation>Sommets</translation>
+ </message>
+ <message>
+ <source>Edges</source>
+ <translation>Arêtes</translation>
+ </message>
+ <message>
+ <source>Faces</source>
+ <translation>Faces</translation>
+ </message>
+ <message>
+ <source>Results</source>
+ <translation>Résultats</translation>
+ </message>
+ <message>
+ <source>Select results</source>
+ <translation>Sélectionnez les résultats</translation>
+ </message>
+ <message>
+ <source>Select parent feature</source>
+ <translation>Sélectionner une entité parente</translation>
+ </message>
+ <message>
+ <source>TInspector</source>
+ <translation>TInspector</translation>
+ </message>
+ <message>
+ <source>Insert a folder before</source>
+ <translation>Insérer un dossier avant</translation>
+ </message>
+ <message>
+ <source>Move into the previous folder</source>
+ <translation>Déplacer dans le dossier précédent</translation>
+ </message>
+ <message>
+ <source>Move into the next folder</source>
+ <translation>Se déplacer dans le dossier suivant</translation>
+ </message>
+ <message>
+ <source>Move out before the folder</source>
+ <translation>Sortir avant le dossier</translation>
+ </message>
+ <message>
+ <source>Move out after the folder</source>
+ <translation>Sortir après le dossier</translation>
+ </message>
+ <message>
+ <source>Set view by inverted normal to face</source>
+ <translation>Définir la vue par normale inversée à la face</translation>
+ </message>
+ <message>
+ <source>Set view by normal to face</source>
+ <translation>Définir la vue par la normale à la face</translation>
+ </message>
+ <message>
+ <source>Selection mode</source>
+ <translation>Mode de sélection</translation>
+ </message>
+ <message>
+ <source>Windows</source>
+ <translation>Fenêtres</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_DataTree</name>
+ <message>
+ <source>History change</source>
+ <translation>Changement l'historique</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_DeflectionDialog</name>
+ <message>
+ <source>Deflection</source>
+ <translation>Déviation</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ErrorDialog</name>
+ <message>
+ <source>Application errors</source>
+ <translation>Erreurs d'application</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ErrorMgr</name>
+ <message>
+ <source>Errors:</source>
+ <translation>Erreurs:</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_FacesPanel</name>
+ <message>
+ <source>Hide Faces</source>
+ <translation>Masquer les faces</translation>
+ </message>
+ <message>
+ <source>Transparent</source>
+ <translation>Transparent</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_InspectionPanel</name>
+ <message>
+ <source>Inspection Panel</source>
+ <translation>Panneau d'inspection</translation>
+ </message>
+ <message>
+ <source>Object</source>
+ <translation>Objet</translation>
+ </message>
+ <message>
+ <source>Sub-shapes</source>
+ <translation>Sous-formes</translation>
+ </message>
+ <message>
+ <source>Number</source>
+ <translation>Nombre</translation>
+ </message>
+ <message>
+ <source>SHAPE</source>
+ <translation>FORME</translation>
+ </message>
+ <message>
+ <source>COMPOUND</source>
+ <translation>ASSEMBLAGE</translation>
+ </message>
+ <message>
+ <source>COMPSOLID</source>
+ <translation>COMPSOLIDE</translation>
+ </message>
+ <message>
+ <source>SOLID</source>
+ <translation>SOLIDE</translation>
+ </message>
+ <message>
+ <source>SHELL</source>
+ <translation>COQUE</translation>
+ </message>
+ <message>
+ <source>FACE</source>
+ <translation>FACE</translation>
+ </message>
+ <message>
+ <source>WIRE</source>
+ <translation>CONTOUR</translation>
+ </message>
+ <message>
+ <source>EDGE</source>
+ <translation>BORD</translation>
+ </message>
+ <message>
+ <source>VERTEX</source>
+ <translation>SOMMET</translation>
+ </message>
+ <message>
+ <source>Type:</source>
+ <translation>Type:</translation>
+ </message>
+ <message>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ <message>
+ <source>Coordinates</source>
+ <translation>Coordonnées</translation>
+ </message>
+ <message>
+ <source>Degenerated</source>
+ <translation>Dégénéré</translation>
+ </message>
+ <message>
+ <source>Line segment</source>
+ <translation>Segment de ligne</translation>
+ </message>
+ <message>
+ <source>Center</source>
+ <translation>Centre</translation>
+ </message>
+ <message>
+ <source>Normal</source>
+ <translation>Normale</translation>
+ </message>
+ <message>
+ <source>Dimensions</source>
+ <translation>Dimensions</translation>
+ </message>
+ <message>
+ <source>Radius</source>
+ <translation>Rayon</translation>
+ </message>
+ <message>
+ <source>Major radius</source>
+ <translation>Rayon majeur</translation>
+ </message>
+ <message>
+ <source>Minor radius</source>
+ <translation>Rayon mineur</translation>
+ </message>
+ <message>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <source>Start point</source>
+ <translation>Point de départ</translation>
+ </message>
+ <message>
+ <source>End point</source>
+ <translation>Point final</translation>
+ </message>
+ <message>
+ <source>Closed</source>
+ <translation>Fermé</translation>
+ </message>
+ <message>
+ <source>Polygon</source>
+ <translation>Polygone</translation>
+ </message>
+ <message>
+ <source>Point</source>
+ <translation>Point</translation>
+ </message>
+ <message>
+ <source>Wire</source>
+ <translation>Contour</translation>
+ </message>
+ <message>
+ <source>Rectangle</source>
+ <translation>Rectangle</translation>
+ </message>
+ <message>
+ <source>Corner</source>
+ <translation>Coin</translation>
+ </message>
+ <message>
+ <source>Width</source>
+ <translation>Largeur</translation>
+ </message>
+ <message>
+ <source>Height</source>
+ <translation>Hauteur</translation>
+ </message>
+ <message>
+ <source>Plane</source>
+ <translation>Plan</translation>
+ </message>
+ <message>
+ <source>Sphere</source>
+ <translation>Sphère</translation>
+ </message>
+ <message>
+ <source>Cylinder</source>
+ <translation>Cylindre</translation>
+ </message>
+ <message>
+ <source>Cone</source>
+ <translation>Cône</translation>
+ </message>
+ <message>
+ <source>Torus</source>
+ <translation>Tore</translation>
+ </message>
+ <message>
+ <source>Face</source>
+ <translation>Face</translation>
+ </message>
+ <message>
+ <source>Box</source>
+ <translation>Boîte</translation>
+ </message>
+ <message>
+ <source>Rotated Box</source>
+ <translation>Boîte tournée</translation>
+ </message>
+ <message>
+ <source>Shell</source>
+ <translation>Coque</translation>
+ </message>
+ <message>
+ <source>Solid</source>
+ <translation>Solide</translation>
+ </message>
+ <message>
+ <source>Bounding box</source>
+ <translation>Boîte englobante</translation>
+ </message>
+ <message>
+ <source>Minimal corner</source>
+ <translation>Coin minimal</translation>
+ </message>
+ <message>
+ <source>Maximal corner</source>
+ <translation>Coin maximal</translation>
+ </message>
+ <message>
+ <source>Origin</source>
+ <translation>Origine</translation>
+ </message>
+ <message>
+ <source>Position</source>
+ <translation>Position</translation>
+ </message>
+ <message>
+ <source>Axis</source>
+ <translation>Axe</translation>
+ </message>
+ <message>
+ <source>Radius 1</source>
+ <translation>Rayon 1</translation>
+ </message>
+ <message>
+ <source>Radius 2</source>
+ <translation>Rayon 2</translation>
+ </message>
+ <message>
+ <source>Depth</source>
+ <translation>Profondeur</translation>
+ </message>
+ <message>
+ <source>Z axis</source>
+ <translation>Axe Z</translation>
+ </message>
+ <message>
+ <source>X axis</source>
+ <translation>Axe X</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ObjectsBrowser</name>
+ <message>
+ <source>Part set</source>
+ <translation>Ensemble</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_OperationMgr</name>
+ <message>
+ <source>All active operations will be aborted.</source>
+ <translation>Toutes les opérations actives seront annulées.</translation>
+ </message>
+ <message>
+ <source>Please validate all your active operations before saving.</source>
+ <translation>Veuillez valider toutes vos opérations actives avant de sauvegarder.</translation>
+ </message>
+ <message>
+ <source>%1 operation will be aborted.</source>
+ <translation>%1 opération sera abandonnée.</translation>
+ </message>
+ <message>
+ <source>Please validate your %1 before saving.</source>
+ <translation>Veuillez valider votre %1 avant de sauvegarder.</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_PropertyPanel</name>
+ <message>
+ <source>Property Panel</source>
+ <translation>Panneau de propriété</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_TransparencyWidget</name>
+ <message>
+ <source>Opaque</source>
+ <translation>Opaque</translation>
+ </message>
+ <message>
+ <source>Transparent</source>
+ <translation>Transparent</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_Workshop</name>
+ <message>
+ <source>Undo</source>
+ <translation>Annuler</translation>
+ </message>
+ <message>
+ <source>Undo last command</source>
+ <translation>Annuler la dernière commande</translation>
+ </message>
+ <message>
+ <source>INF_DESK_TOOLBAR_STANDARD</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <source>Redo</source>
+ <translation>Refaire</translation>
+ </message>
+ <message>
+ <source>Redo last command</source>
+ <translation>Refaire la dernière commande</translation>
+ </message>
+ <message>
+ <source>Export native...</source>
+ <translation>Exporter natif...</translation>
+ </message>
+ <message>
+ <source>Export the current document into a native file</source>
+ <translation>Exporter le document actuel dans un fichier natif</translation>
+ </message>
+ <message>
+ <source>Import native...</source>
+ <translation>Importer natif...</translation>
+ </message>
+ <message>
+ <source>Import native file</source>
+ <translation>Importer un fichier natif</translation>
+ </message>
+ <message>
+ <source>Save</source>
+ <translation>Enregistrer</translation>
+ </message>
+ <message>
+ <source>Save the document</source>
+ <translation>Enregistrer le document</translation>
+ </message>
+ <message>
+ <source>Save as...</source>
+ <translation>Enregistrer sous...</translation>
+ </message>
+ <message>
+ <source>Save the document into a file</source>
+ <translation>Enregistrer le document dans un fichier</translation>
+ </message>
+ <message>
+ <source>Open...</source>
+ <translation>Ouvrir...</translation>
+ </message>
+ <message>
+ <source>Open a new document</source>
+ <translation>Ouvrir un nouveau document</translation>
+ </message>
+ <message>
+ <source>Auto rebuild</source>
+ <translation>Reconstruction automatique</translation>
+ </message>
+ <message>
+ <source>Blocks immediate apply of modifications</source>
+ <translation>Bloque l'application immédiate des modifications</translation>
+ </message>
+ <message>
+ <source>Preferences</source>
+ <translation>Préférences</translation>
+ </message>
+ <message>
+ <source>Edit preferences</source>
+ <translation>Modifier les préférences</translation>
+ </message>
+ <message>
+ <source>Exit</source>
+ <translation>Quitter</translation>
+ </message>
+ <message>
+ <source>Exit application</source>
+ <translation>Quitter l’application</translation>
+ </message>
+ <message>
+ <source>Save current file</source>
+ <translation>Enregistrer le fichier courant</translation>
+ </message>
+ <message>
+ <source>The document is modified, save before opening another?</source>
+ <translation>Le document est modifié, sauvegarder avant d'en ouvrir un autre ?</translation>
+ </message>
+ <message>
+ <source>Open file</source>
+ <translation>Fichier ouvert</translation>
+ </message>
+ <message>
+ <source>Select name to save file...</source>
+ <translation>Sélectionnez le nom pour enregistrer le fichier...</translation>
+ </message>
+ <message>
+ <source>Show object</source>
+ <translation>Montrer l'objet</translation>
+ </message>
+ <message>
+ <source>'%1'
+ are hidden by %2:
+Remove objects from the panel to be displayed?</source>
+ <translation>'%1'
+ est caché par %2 :
+Supprimer des objets du panneau à afficher ?</translation>
+ </message>
+ <message>
+ <source>Warning</source>
+ <translation>Attention</translation>
+ </message>
+ <message>
+ <source>Unable to open the file.</source>
+ <translation>Impossible d'ouvrir le fichier.</translation>
+ </message>
+ <message>
+ <source>The document is modified, save before exit?</source>
+ <translation>Le document est modifié, enregistrer avant de quitter ?</translation>
+ </message>
+ <message>
+ <source>Information about module "%1" doesn't exist.</source>
+ <translation>Les informations sur le module "%1" n'existent pas.</translation>
+ </message>
+ <message>
+ <source>Object browser</source>
+ <translation>Navigateur d'objet</translation>
+ </message>
+ <message>
+ <source>All features are relevant, there is nothing to be deleted</source>
+ <translation>Toutes les fonctionnalités sont pertinentes, il n'y a rien à supprimer</translation>
+ </message>
+ <message>
+ <source>Transparency</source>
+ <translation>Transparence</translation>
+ </message>
+ <message>
+ <source>Find results</source>
+ <translation>Trouver des résultats</translation>
+ </message>
+ <message>
+ <source>Results not found</source>
+ <translation>Résultats non trouvés</translation>
+ </message>
+</context>
+</TS>
<file>pictures/color.png</file>
<file>pictures/normal-view-inversed.png</file>
<file>pictures/normal-view.png</file>
+ <file>pictures/move_to_end.png</file>
+ <file>pictures/move_to_end_split.png</file>
</qresource>
</RCC>
model.testNbSubResults(aPartFeature, [0])
model.testNbSubShapes(aPartFeature, GeomAPI_Shape.SOLID, [32])
model.testNbSubShapes(aPartFeature, GeomAPI_Shape.FACE, [875])
- model.testNbSubShapes(aPartFeature, GeomAPI_Shape.EDGE, [4665])
- model.testNbSubShapes(aPartFeature, GeomAPI_Shape.VERTEX, [9330])
- model.testResultsVolumes(aPartFeature, [145241798.705457538])
+ model.testNbSubShapes(aPartFeature, GeomAPI_Shape.EDGE, [4659])
+ model.testNbSubShapes(aPartFeature, GeomAPI_Shape.VERTEX, [9318])
+ model.testResultsVolumes(aPartFeature, [145241798.70546785])
export DISPLAY="localhost:0.0"
+# check for __init__.py in the SHAPER's Python scripts directory
+# for correct parsing PYTHONPATH and use the actual version of SHAPER
+# instead of distributed with SALOME
+if [[ ! -f ${SHAPER_PYTHON_SCRIPTS_DIR}/salome/__init__.py ]]; then
+ touch ${SHAPER_PYTHON_SCRIPTS_DIR}/salome/__init__.py
+fi
+
if [[ $# > 0 ]]; then
ctest --no-compress-output -T Test "$@" -R $1
else