# Sketcher: Change radius of circular edges while dragging a point on the edge
SET(SKETCHER_CHANGE_RADIUS_WHEN_MOVE TRUE)
+SET(MAKE_TRANSLATION NO)
+
+IF(${MAKE_TRANSLATION})
+ ADD_DEFINITIONS( -DMAKE_TRANSLATION )
+ENDIF(${MAKE_TRANSLATION})
+
+
ADD_SUBDIRECTORY (src/Config)
ADD_SUBDIRECTORY (src/Events)
ADD_SUBDIRECTORY (src/Selector)
#!/bin/bash -x
-export SALOME_DIR=/dn46/SALOME/series9x/current-2019-08-19
+export SALOME_DIR=/dn46/SALOME/series9x/current-2019-10-04
# Path to sources
export SOURCES_DIR=$(pwd)
mv -f covElse_res covElse
fi
done
-# remove SketchPlugin's Ellipse feature (unsupported yet)
-lcov -r covElse SketchPlugin*Ellipse* --output-file covElse_res -q
-mv -f covElse_res covElse
rm -rf lcov_htmlElse
genhtml covElse --output-directory lcov_htmlElse -q
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
if(aConstruction.get()) {
if(aConstruction->isInfinite()) {
- theError = "Inifinte objects not acceptable.";
+ theError = "Infinite objects not acceptable.";
return false;
}
<context>
<name>Edge:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
<message>
- <source>Inifinte objects not acceptable.</source>
- <translation>Inifinte objects not acceptable.</translation>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Infinite objects not acceptable.</translation>
</message>
</context>
<context>
<context>
<name>Face:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
<message>
- <source>Inifinte objects not acceptable.</source>
- <translation>Inifinte objects not acceptable.</translation>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Infinite objects not acceptable.</translation>
</message>
</context>
<context>
<context>
<name>Vertex:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
<message>
- <source>Inifinte objects not acceptable.</source>
- <translation>Inifinte objects not acceptable.</translation>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Infinite objects not acceptable.</translation>
</message>
</context>
<context>
<context>
<name>Wire:base_objects:BuildPlugin_ValidatorBaseForBuild</name>
<message>
- <source>Inifinte objects not acceptable.</source>
- <translation>Inifinte objects not acceptable.</translation>
+ <source>Infinite objects not acceptable.</source>
+ <translation>Infinite objects not acceptable.</translation>
</message>
</context>
<context>
--- /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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "first_point" is not initialized.</source>
+ <translation>AA</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>
SET(TEXT_RESOURCES
BuildPlugin_msg_en.ts
+ BuildPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
concealment="true">
<validator id="GeomValidators_DifferentShapes"/>
</multi_selector>
- <boolvalue id="closed" label="Closed" tooltip="Makes the polyline closed." default="false"/>
+ <boolvalue id="closed" label="Closed" tooltip="Closes the polyline." default="false"/>
<validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
</source>
AttributeSelectionListPtr anAttrList = aBase->selectionList(CollectionPlugin_Group::LIST_ID());
- theDumper << aBase << " = model.addGroup(" << aDocName << ", " << anAttrList;
+ theDumper << aBase << " = model.addGroup(" << aDocName << ", ";
+ if (anAttrList->isWholeResultAllowed() && !anAttrList->selectionType().empty())
+ theDumper<<"\""<<anAttrList->selectionType()<<"\", ";
+ theDumper << anAttrList;
if (anAttrList->isGeometricalSelection())
theDumper <<", True";
theDumper << ")" << std::endl;
aFeature->selectionList(CollectionPlugin_Group::LIST_ID())->setGeometricalSelection(true);
return GroupPtr(new CollectionAPI_Group(aFeature, theGroupList));
}
+
+//==================================================================================================
+GroupPtr addGroup(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::string& theSelectionType,
+ const std::list<ModelHighAPI_Selection>& theGroupList,
+ const bool theShareSameTopology)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature = thePart->addFeature(CollectionAPI_Group::ID());
+ aFeature->selectionList(CollectionPlugin_Group::LIST_ID())->setSelectionType(theSelectionType);
+ if (theShareSameTopology)
+ aFeature->selectionList(CollectionPlugin_Group::LIST_ID())->setGeometricalSelection(true);
+ return GroupPtr(new CollectionAPI_Group(aFeature, theGroupList));
+}
const std::list<ModelHighAPI_Selection>& theGroupList,
const bool theShareSameTopology = false);
+/// \ingroup CPPHighAPI
+/// \brief Create Group with the additional selection type for case the whole result selected.
+COLLECTIONAPI_EXPORT
+GroupPtr addGroup(const std::shared_ptr<ModelAPI_Document>& thePart,
+ const std::string& theSelectionType,
+ const std::list<ModelHighAPI_Selection>& theGroupList,
+ const bool theShareSameTopology = false);
+
#endif // CollectionAPI_Group_H_
SET(TEXT_RESOURCES
CollectionPlugin_msg_en.ts
+ CollectionPlugin_msg_fr.ts
)
# sources / moc wrappings
TestGroupMove18.py
TestGroupMove19.py
TestGroupMove20.py
+ TestGroupMove21.py
+ TestGroupMove22.py
+ TestGroupMove23.py
+ TestGroupMove24.py
+ TestGroupMove25.py
TestGroupShareTopology.py
TestGroupAddition.py
TestGroupAddition_Error.py
TestGroupIntersection.py
TestGroupIntersection_Error.py
TestGroupSubstraction.py
+ TestGroupSubstraction2.py
TestGroupSubstraction_Error1.py
TestGroupSubstraction_Error2.py
Test2977.py
+ TestGroupWholeResult1.py
+ TestGroupWholeResult2.py
+ Test3031.py
)
void CollectionPlugin_Group::initAttributes()
{
- data()->addAttribute(CollectionPlugin_Group::LIST_ID(),
- ModelAPI_AttributeSelectionList::typeId());
+ AttributeSelectionListPtr aList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(
+ data()->addAttribute(LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
+ aList->setWholeResultAllowed(true); // allow to select the whole result
}
void CollectionPlugin_Group::execute()
#include <GeomAlgoAPI_CompoundBuilder.h>
#include <GeomAlgoAPI_ShapeTools.h>
-typedef std::set<GeomShapePtr, GeomAPI_Shape::ComparatorWithOri> SetOfShape;
+typedef std::set<GeomShapePtr, GeomAPI_Shape::Comparator> SetOfShape;
CollectionPlugin_GroupSubstraction::CollectionPlugin_GroupSubstraction()
{
<translation>Constructions not allowed for selection.</translation>
</message>
</context>
- <context>
- <name>Group:group_list:GeomValidators_BodyShapes</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation>Attribute "%1" does not supported by "GeomValidators_BodyShapes" validator.</translation>
- </message>
- </context>
<context>
<name>Group:Model_FeatureValidator</name>
<message>
--- /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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "group_list" is not initialized.</source>
+ <translation>AA</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
+#
+
+# Test of movement of the group of whole result with different results shape types: only one shape type must be in the moved group
+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"))
+SketchCircle_1 = Sketch_1.addCircle(17.20575221238938, 2.793141592920342, 8.375699762004958)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOZ"))
+SketchLine_1 = Sketch_2.addLine(24.25155410709516, 6.639479956172791, 20.59251568321609, -12.31511385947313)
+model.do()
+Face_1 = model.addFace(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")])
+Edge_1 = model.addEdge(Part_1_doc, [model.selection("EDGE", "Sketch_2/SketchLine_1")])
+Group_1 = model.addGroup(Part_1_doc, "Edges", [model.selection("EDGE", "Edge_1_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Face_1_1"), model.selection("EDGE", "Edge_1_1")], 20190506)
+model.do()
+# move group after the partition
+Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
+model.end()
+
+# check that only two edges are in the group result, no face
+assert(len(Group_1.feature().results())==1)
+model.testNbSubShapes(Group_1, GeomAPI_Shape.EDGE, [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
+#
+
+# Test move the group in history for selection of a whole result
+
+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(35.07635467980296, 23.01108374384237, -25.74753694581282, 23.01108374384237)
+SketchLine_2 = Sketch_1.addLine(-25.74753694581282, 23.01108374384237, -25.74753694581282, -23.13546798029557)
+SketchLine_3 = Sketch_1.addLine(-25.74753694581282, -23.13546798029557, 35.07635467980296, -23.13546798029557)
+SketchLine_4 = Sketch_1.addLine(35.07635467980296, -23.13546798029557, 35.07635467980296, 23.01108374384237)
+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())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 80, 0)
+# selection of a whole result: 6 faces of a box
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("SOLID", "Extrusion_1_1")])
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [6])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3"))
+SketchCircle_1 = Sketch_2.addCircle(-7.736745115674536, 52.14422040986419, 6.760003867274182)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+model.do()
+# move group after the extrusion-cut, so, it refers to it
+Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature())
+model.end()
+
+# check that there is a hole appeared in the group-results
+assert(len(Group_1.feature().results())==1)
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [8])
+
+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
+#
+
+# Test move the group in history for selection of a whole result of a compsolid
+
+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(-25.00123152709361, 27.48891625615764, 27.86206896551725, 27.48891625615764)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(27.86206896551725, 27.48891625615764, -23.88177339901478, -20.02586206896552)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-23.88177339901478, -20.02586206896552, 28.73275862068966, -20.02586206896552)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchLine_4 = Sketch_1.addLine(28.73275862068966, -20.02586206896552, 27.86206896551725, 27.48891625615764)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.endPoint())
+SketchLine_5 = Sketch_1.addLine(-25.00123152709361, 27.48891625615764, 28.73275862068966, -20.02586206896552)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_5.endPoint())
+model.do()
+Extrusion_1_objects = [model.selection("FACE", "Sketch_1/Face-SketchLine_5f-SketchLine_2r-SketchLine_1r"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_5f-SketchLine_4f"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_3f-SketchLine_5r")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection(), 10, 0)
+# selection of a whole result: 5x3-2 faces (2 faces are shared)
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPSOLID", "Extrusion_1_1")])
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [13])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("COMPSOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1_1/To_Face"))
+SketchCircle_1 = Sketch_2.addCircle(13.4282260278248, 11.79859034244854, 3.718064241992405)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+model.do()
+# move group after the extrusion-cut, so, it refers to it
+Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature())
+model.end()
+
+# check that there is a hole appeared in two solids: +4 faces (1 splitted planar, 3 faces of cylinder, divided by seam)
+assert(len(Group_1.feature().results())==1)
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [17])
+
+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
+#
+
+# Test move the group in history for selection of a whole feature
+
+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(35.07635467980296, 23.01108374384237, -25.74753694581282, 23.01108374384237)
+SketchLine_2 = Sketch_1.addLine(-25.74753694581282, 23.01108374384237, -25.74753694581282, -23.13546798029557)
+SketchLine_3 = Sketch_1.addLine(-25.74753694581282, -23.13546798029557, 35.07635467980296, -23.13546798029557)
+SketchLine_4 = Sketch_1.addLine(35.07635467980296, -23.13546798029557, 35.07635467980296, 23.01108374384237)
+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())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 80, 0)
+# selection of a whole feature: 6 faces of a box
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [6])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3"))
+SketchCircle_1 = Sketch_2.addCircle(-7.736745115674536, 52.14422040986419, 6.760003867274182)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+model.do()
+# move group after the extrusion-cut, so, it refers to it
+Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature())
+model.end()
+
+# check that there is a hole appeared in the group-results
+assert(len(Group_1.feature().results())==1)
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [8])
+
+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
+#
+
+# Test move the group in history for selection of a whole feature that produces compsolid
+
+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(-25.00123152709361, 27.48891625615764, 27.86206896551725, 27.48891625615764)
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchLine_2 = Sketch_1.addLine(27.86206896551725, 27.48891625615764, -23.88177339901478, -20.02586206896552)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(-23.88177339901478, -20.02586206896552, 28.73275862068966, -20.02586206896552)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchLine_4 = Sketch_1.addLine(28.73275862068966, -20.02586206896552, 27.86206896551725, 27.48891625615764)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.endPoint())
+SketchLine_5 = Sketch_1.addLine(-25.00123152709361, 27.48891625615764, 28.73275862068966, -20.02586206896552)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_5.endPoint())
+model.do()
+Extrusion_1_objects = [model.selection("FACE", "Sketch_1/Face-SketchLine_5f-SketchLine_2r-SketchLine_1r"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_5f-SketchLine_4f"), model.selection("FACE", "Sketch_1/Face-SketchLine_2f-SketchLine_3f-SketchLine_5r")]
+Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection(), 10, 0)
+# selection of a whole result: 5x3-2 faces (2 faces are shared)
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [13])
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 10, [model.selection("COMPSOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1_1/To_Face"))
+SketchCircle_1 = Sketch_2.addCircle(13.4282260278248, 11.79859034244854, 3.718064241992405)
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+model.do()
+# move group after the extrusion-cut, so, it refers to it
+Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature())
+model.end()
+
+# check that there is a hole appeared in two solids: +4 faces (1 splitted planar, 3 faces of cylinder, divided by seam)
+assert(len(Group_1.feature().results())==1)
+model.testNbSubShapes(Group_1, GeomAPI_Shape.FACE, [17])
+
+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
+#
+
+# Test move the group in history for selection of a whole features
+# with many modifications of this feature, and joining them in one.
+
+from SketchAPI import *
+
+from salome.shaper import model
+from ModelAPI 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, 9.999999999999998, -40, 10)
+SketchLine_2 = Sketch_1.addLine(-40, 10, -40, -10)
+SketchLine_3 = Sketch_1.addLine(-40, -10, -20, -9.999999999999998)
+SketchLine_4 = Sketch_1.addLine(-20, -9.999999999999998, -20, 9.999999999999998)
+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())
+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_5 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchCircle_1.results()[1])
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchLine_3.result(), SketchCircle_1.results()[1])
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_4.result(), 20, True)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10)
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_4.result())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 30, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 15, 0)
+Group_1 = model.addGroup(Part_1_doc, "Vertices", [model.selection("COMPOUND", "all-in-Extrusion_1")])
+Group_2 = model.addGroup(Part_1_doc, "Vertices", [model.selection("COMPOUND", "all-in-Extrusion_2")])
+Group_3 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Extrusion_1"), model.selection("COMPOUND", "all-in-Extrusion_2")])
+ExtrusionFuse_1 = model.addExtrusionFuse(Part_1_doc, [], model.selection(), 12, 0, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4"))
+SketchCircle_2 = Sketch_2.addCircle(-2.3396523840492e-15, 15, 7)
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_2.results()[1], 7)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_1][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4]"), False)
+SketchLine_5 = SketchProjection_2.createdFeature()
+SketchConstraintDistance_2 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_5.result(), 10, True)
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_4][Extrusion_1_1/To_Face]"), False)
+SketchLine_6 = SketchProjection_3.createdFeature()
+SketchConstraintDistance_3 = Sketch_2.setDistance(SketchCircle_2.center(), SketchLine_6.result(), 15, True)
+ExtrusionFuse_1.setNestedSketch(Sketch_2)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 50, 50, [model.selection("SOLID", "ExtrusionFuse_1_1"), model.selection("SOLID", "Extrusion_2_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionFuse_1_1/To_Face"))
+SketchProjection_4 = Sketch_3.addProjection(model.selection("VERTEX", "[ExtrusionFuse_1_1/Generated_Face&Sketch_2/SketchCircle_2_2][ExtrusionFuse_1_1/To_Face]__cc"), False)
+SketchPoint_2 = SketchProjection_4.createdFeature()
+SketchCircle_3 = Sketch_3.addCircle(-2.3396523840492e-15, 15, 5)
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchPoint_2.result(), SketchCircle_3.center())
+SketchConstraintRadius_3 = Sketch_3.setRadius(SketchCircle_3.results()[1], 5)
+ExtrusionCut_1.setNestedSketch(Sketch_3)
+Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "ExtrusionCut_1_1"), model.selection("SOLID", "ExtrusionCut_1_2")], True, 20190506)
+model.do()
+# move groups after the final fuse
+Part_1_doc.moveFeature(Group_1.feature(), Fuse_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+Part_1_doc.moveFeature(Group_3.feature(), Group_2.feature())
+model.end()
+
+aFactory = ModelAPI_Session.get().validators()
+for group in [Group_1, Group_2, Group_3]:
+ selectionList = group.feature().selectionList("group_list")
+ assert(selectionList.size() == 1)
+ assert(aFactory.validate(group.feature()))
--- /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
+#
+
+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"))
+SketchLine_1 = Sketch_1.addLine(-30, -17.32050807568877, 30, -17.32050807568877)
+SketchLine_2 = Sketch_1.addLine(30, -17.32050807568877, 0, 34.64101615137755)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 34.64101615137755, -30, -17.32050807568877)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_2.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_1.result(), SketchLine_3.result())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchLine_4 = Sketch_1.addLine(30, -17.32050807568877, 0, 0)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_4.startPoint())
+SketchLine_5 = Sketch_1.addLine(0, 0, 0, 34.64101615137755)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(-30, -17.32050807568877, 0, 0)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.endPoint())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_5.result())
+SketchConstraintEqual_4 = Sketch_1.setEqual(SketchLine_4.result(), SketchLine_6.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_6.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 60)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), 10, 0)
+Group_1_objects = [model.selection("FACE", "Extrusion_1_1_3/Generated_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Extrusion_1_1_3/To_Face"), model.selection("FACE", "Extrusion_1_1_3/From_Face"), model.selection("FACE", "Extrusion_1_1_3/Generated_Face&Sketch_1/SketchLine_3"), model.selection("FACE", "Extrusion_1_1_3/Generated_Face&Sketch_1/SketchLine_5"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchLine_6"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchLine_1"), model.selection("FACE", "Extrusion_1_1_1/From_Face"), model.selection("FACE", "Extrusion_1_1_1/To_Face"), model.selection("FACE", "Extrusion_1_1_1/Generated_Face&Sketch_1/SketchLine_4"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_4"), model.selection("FACE", "Extrusion_1_1_2/To_Face"), model.selection("FACE", "Extrusion_1_1_2/From_Face"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_2"), model.selection("FACE", "Extrusion_1_1_2/Generated_Face&Sketch_1/SketchLine_5")]
+Group_1 = model.addGroup(Part_1_doc, "Faces", Group_1_objects)
+Group_2 = model.addGroup(Part_1_doc, "Faces", [model.selection("SOLID", "Extrusion_1_1_2")])
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2")])
+model.end()
+
+from GeomAPI import *
+
+model.testNbResults(GroupSubstraction_1, 1)
+model.testNbSubResults(GroupSubstraction_1, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.SOLID, [0])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.FACE, [7])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.EDGE, [24])
+model.testNbSubShapes(GroupSubstraction_1, GeomAPI_Shape.VERTEX, [48])
+
+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 result 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(-16, -4, -4, 29)
+SketchLine_2 = Sketch_1.addLine(-4, 29, 21, -9)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(21, -9, -16, -4)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_3r-SketchLine_2r-SketchLine_1r")], model.selection(), 10, 0)
+Group_1 = model.addGroup(Part_1_doc, "EDGE", [model.selection("SOLID", "Extrusion_1_1")])
+model.end()
+
+# check the group result: it must be compound of 9 edges
+assert(Group_1.groupList().selectionType() == "EDGE")
+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.isEdge())
+ aNum = aNum + 1
+ anIter.next()
+
+assert(aNum == 9)
+
+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 result (by feature) in group selection
+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)
+Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPOUND", "all-in-Box_1")])
+Group_2 = model.addGroup(Part_1_doc, "Faces", [model.selection("FACE", "Box_1_1/Left"), model.selection("FACE", "Box_1_1/Top")])
+GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2")])
+model.end()
+
+aResultShape = GroupSubstraction_1.feature().firstResult().shape()
+
+from GeomAPI import GeomAPI_ShapeIterator
+anIter = GeomAPI_ShapeIterator(aResultShape)
+aNum = 0
+while anIter.more():
+ aFace = anIter.current()
+ assert(aFace.isFace())
+ aNum = aNum + 1
+ anIter.next()
+
+assert(aNum == 4) # 6 from the whole result minus 2 from the second group (local selection)
+
+
+assert(model.checkPythonDump())
<multi_selector id="group_list"
label="Base groups:"
tooltip="Select a set of groups"
- shape_types="objects">
+ shape_types="objects"
+ allow_objects="Group">
<validator id="CollectionPlugin_OperationAttribute"/>
</multi_selector>
</source>
<multi_selector id="group_list"
label="Main groups:"
tooltip="Select a set of groups"
- shape_types="objects">
+ shape_types="objects"
+ allow_objects="Group">
<validator id="CollectionPlugin_OperationAttribute" parameters="tools_list"/>
</multi_selector>
<multi_selector id="tools_list"
label="Tool groups:"
tooltip="Select a set of groups"
- shape_types="objects">
+ shape_types="objects"
+ allow_objects="Group">
<validator id="CollectionPlugin_OperationAttribute" parameters="group_list"/>
</multi_selector>
</source>
model.exportToGEOM(Part_1_doc)
model.end()
-# check that in GEOM module there are reuslts:
+# check that in GEOM module there are results:
# extrusion of the first part
# extrusion with group of the second part
# extrusion with filed of the third part
--- /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
+#
+import salome
+
+from SketchAPI import *
+from salome.shaper import model
+
+from salome.geom import geomBuilder
+
+import os
+import tempfile
+
+salome.salome_init(1)
+geompy = geomBuilder.New()
+
+## Get the last object published in the GEOM section of the object browser
+def getGEOMShape(index):
+ sb = salome.myStudy.NewBuilder()
+ comp = salome.myStudy.FindComponent("GEOM")
+ obj = None
+ if comp:
+ iterator = salome.myStudy.NewChildIterator( comp )
+ sobj = None
+ i = index + 1
+ while iterator.More() and i:
+ sobj = iterator.Value()
+ iterator.Next()
+ i = i - 1
+ if i == 0 and sobj:
+ obj = sobj.GetObject()
+ else:
+ raise Exception("GEOM component " + str(index) + " not found.")
+ return obj
+
+## Get the sub-object i of an object in the object browser
+# Numerotation starts at 1
+def getSubObject(obj, i):
+ ok, sub_sobj = salome.ObjectToSObject(obj).FindSubObject(i)
+ if not ok:
+ raise Exception("No child found at %i for %s"%(i, obj.GetName()))
+ sub_obj = sub_sobj.GetObject()
+ return sub_obj
+
+
+def testExportToGEOM():
+ 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("YOZ"))
+ SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+ SketchPoint_1 = SketchProjection_1.createdFeature()
+ SketchCircle_1 = Sketch_1.addCircle(0, 0, 25)
+ SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+ SketchCircle_2 = Sketch_1.addCircle(20, -15, 20)
+ SketchCircle_3 = Sketch_1.addCircle(0, 25, 24.7213595499958)
+ SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchCircle_1.results()[1], SketchCircle_3.center())
+ SketchCircle_4 = Sketch_1.addCircle(-20, -15, 20)
+ SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchCircle_1.results()[1], SketchCircle_4.center())
+ SketchConstraintTangent_1 = Sketch_1.setTangent(SketchCircle_4.results()[1], SketchCircle_2.results()[1])
+ SketchConstraintTangent_2 = Sketch_1.setTangent(SketchCircle_3.results()[1], SketchCircle_2.results()[1])
+ SketchConstraintTangent_3 = Sketch_1.setTangent(SketchCircle_4.results()[1], SketchCircle_3.results()[1])
+ SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchCircle_2.center(), SketchCircle_1.results()[1])
+ SketchConstraintEqual_1 = Sketch_1.setEqual(SketchCircle_2.results()[1], SketchCircle_4.results()[1])
+ SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_2.results()[1], 20)
+ SketchConstraintRadius_2 = Sketch_1.setRadius(SketchCircle_1.results()[1], 25)
+ SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OZ"), False)
+ SketchLine_1 = SketchProjection_2.createdFeature()
+ SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_1.result(), SketchCircle_3.center())
+ model.do()
+ Extrusion_1_objects = [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchCircle_4_2r-SketchCircle_4_2r-SketchCircle_3_2r"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchCircle_3_2r-SketchCircle_2_2r-SketchCircle_2_2r"), model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f-SketchCircle_2_2r-SketchCircle_4_2r")]
+ Extrusion_1 = model.addExtrusion(Part_1_doc, Extrusion_1_objects, model.selection(), 10, 0)
+ # select all results of an extrusion feature
+ Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("COMPSOLID", "all-in-Extrusion_1")])
+ Group_2 = model.addGroup(Part_1_doc, "Faces", [model.selection("SOLID", "Extrusion_1_2")])
+ GroupSubstraction_1 = model.addGroupSubstraction(Part_1_doc, [model.selection("COMPOUND", "Group_1")], [model.selection("COMPOUND", "Group_2")])
+ model.do()
+ model.exportToGEOM(Part_1_doc)
+ model.end()
+
+ # check that in GEOM module there are 3-SOLIDs-reuslts, with 2 groups each
+ shape1 = getGEOMShape(0)
+ assert(shape1)
+ assert(shape1.GetName() == "Extrusion_1_1")
+ assert(geompy.NumberOfSolids(shape1) == 1)
+ assert(salome.ObjectToSObject(shape1).FindSubObject(1)[1])
+ assert(salome.ObjectToSObject(shape1).FindSubObject(1)[1].GetName() == "Group_1")
+ assert(salome.ObjectToSObject(shape1).FindSubObject(2)[1])
+ assert(salome.ObjectToSObject(shape1).FindSubObject(2)[1].GetName() == "GroupSubstraction_1")
+
+ shape2 = getGEOMShape(1)
+ assert(shape2)
+ assert(shape2.GetName() == "Extrusion_1_2")
+ assert(geompy.NumberOfSolids(shape2) == 1)
+ assert(salome.ObjectToSObject(shape2).FindSubObject(1)[1])
+ assert(salome.ObjectToSObject(shape2).FindSubObject(1)[1].GetName() == "Group_1")
+ assert(salome.ObjectToSObject(shape2).FindSubObject(2)[1])
+ assert(salome.ObjectToSObject(shape2).FindSubObject(2)[1].GetName() == "Group_2")
+
+ shape3 = getGEOMShape(2)
+ assert(shape3)
+ assert(shape3.GetName() == "Extrusion_1_3")
+ assert(geompy.NumberOfSolids(shape3) == 1)
+ assert(salome.ObjectToSObject(shape3).FindSubObject(1)[1])
+ assert(salome.ObjectToSObject(shape3).FindSubObject(1)[1].GetName() == "Group_1")
+ assert(salome.ObjectToSObject(shape3).FindSubObject(2)[1])
+ assert(salome.ObjectToSObject(shape3).FindSubObject(2)[1].GetName() == "GroupSubstraction_1")
+
+ shape4 = getGEOMShape(3)
+ assert(not shape4)
+
+
+if __name__ == '__main__':
+ testExportToGEOM()
--- /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
+#
+
+import salome
+from salome.shaper import model
+
+from salome.geom import geomBuilder
+
+import os
+import tempfile
+
+salome.salome_init(1)
+geompy = geomBuilder.New()
+
+## Get the last object published in the GEOM section of the object browser
+def getLastGEOMShape():
+ sb = salome.myStudy.NewBuilder()
+ comp = salome.myStudy.FindComponent("GEOM")
+ obj = None
+ if comp:
+ iterator = salome.myStudy.NewChildIterator( comp )
+ sobj = None
+ while iterator.More():
+ sobj = iterator.Value()
+ iterator.Next()
+ if sobj:
+ obj = sobj.GetObject()
+ else:
+ raise Exception("GEOM component not found.")
+ return obj
+
+## Get the sub-object i of an object in the object browser
+# Numerotation starts at 1
+def getSubObject(obj, i):
+ ok, sub_sobj = salome.ObjectToSObject(obj).FindSubObject(i)
+ if not ok:
+ raise Exception("No child found at %i for %s"%(i, obj.GetName()))
+ sub_obj = sub_sobj.GetObject()
+ return sub_obj
+
+def dumpShaper(fileName):
+ model.begin()
+ dump=model.moduleDocument().addFeature("Dump")
+ dump.string("file_path").setValue(fileName)
+ dump.string("file_format").setValue("py")
+ dump.boolean("topological_naming").setValue(True)
+ dump.boolean("geometric_selection").setValue(False)
+ dump.boolean("weak_naming").setValue(False)
+ model.do()
+ model.end()
+ pass
+
+# Create 2 boxes
+# Create a group of all edges of the first box (whole result)
+# Create a group of all faces of the whole partition result (whole result)
+# exportToGEOM
+# Check the result
+# Check the dump
+def testExportToGEOM():
+
+ 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, 20, 20, 20)
+ Translation_1 = model.addTranslation(Part_1_doc, [model.selection("SOLID", "Box_1_1")], model.selection("EDGE", "PartSet/OX"), -10)
+ Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Translation_1_1"), model.selection("SOLID", "Box_2_1")])
+ Group_1 = model.addGroup(Part_1_doc, "EDGE", [model.selection("COMPSOLID", "Partition_1_1_1")])
+ Group_2 = model.addGroup(Part_1_doc, "FACE", [model.selection("COMPSOLID", "Partition_1_1")])
+ model.do()
+
+ model.exportToGEOM(Part_1_doc)
+ model.end()
+
+ # Check that the GEOM object has 1 compsolid and 2 solids
+ geomObject_1 = getLastGEOMShape()
+ assert geompy.NumberOfSubShapes(geomObject_1, geompy.ShapeType["COMPSOLID"]) == 1
+ assert geompy.NumberOfSolids(geomObject_1) == 2
+
+ # Check that the group has 12 edges
+ geomGroup_1 = getSubObject(geomObject_1, 1)
+ assert geompy.NumberOfEdges(geomGroup_1) == 12
+
+ # Check that the group has 6+6 faces
+ geomGroup_2 = getSubObject(geomObject_1, 2)
+ assert geompy.NumberOfFaces(geomGroup_2) == 12
+
+ # Dump the salome study (only CORBA modules, SHAPER dump is not in it)
+ tempdir = tempfile.gettempdir()
+ dumpFileGeomBase = "dump_test_geom"
+ dumpFileGeom = os.path.join(tempdir, "%s.py"%dumpFileGeomBase)
+ salome.myStudy.DumpStudy(tempdir, dumpFileGeomBase, True, False)
+
+ # Dump SHAPER
+ dumpFileShaper = os.path.join(tempdir, "dump_test_shaper.py")
+ dumpShaper(dumpFileShaper)
+
+ # Load SHAPER dump
+ exec(compile(open(dumpFileShaper).read(), dumpFileShaper, 'exec'))
+
+ # Load GEOM dump
+ exec(compile(open(dumpFileGeom).read(), dumpFileGeom, 'exec'))
+
+ # Clean files
+ files = [dumpFileGeom, dumpFileShaper]
+ for f in files:
+ os.remove(f)
+
+ pass
+
+if __name__ == '__main__':
+ testExportToGEOM()
TestExportToGEOM
TestExportToGEOMAllGroupsAndFields
TestExportToGEOMPartSet
+ TestExportToGEOMWholeResult
+ TestExportToGEOMWholeFeature
Test2882
)
plugin-Connector.xml
)
-ADD_CUSTOM_TARGET(ConnectorPlugin SOURCES ${PYTHON_FILES} ${XML_RESOURCES})
+SET(TEXT_RESOURCES
+ ConnectorPlugin_msg_fr.ts
+)
+
+SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
+
+ADD_CUSTOM_TARGET(ConnectorPlugin SOURCES ${PYTHON_FILES} ${XML_RESOURCES} ${TEXT_RESOURCES})
INSTALL(FILES ${PYTHON_FILES} DESTINATION ${SHAPER_INSTALL_PYTHON_FILES})
-INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+INSTALL(FILES ${XML_RESOURCES} ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Connector)
--- /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>
<feature
id="ExportToGEOM"
title="Export to GEOM"
- tooltip="Export all bodies and groups into GEOM module"
+ tooltip="Export all results and groups into GEOM module"
icon="icons/Connector/geom_export.png"
helpfile="ConnectorPlugin/ConnectorPlugin.html"/>
</group>
SET(TEXT_RESOURCES
ConstructionPlugin_msg_en.ts
+ ConstructionPlugin_msg_fr.ts
)
SET(PROJECT_LIBRARIES
PLANE_SIZE, "0", "1000");
Config_PropManager::registerProp(SKETCH_TAB_NAME, "planes_thickness", "Thickness",
Config_Prop::IntSpin, SKETCH_WIDTH);
+ Config_PropManager::registerProp(SKETCH_TAB_NAME, "angular_tolerance", "Angular tolerance",
+ Config_Prop::DblSpin, "0.04");
Config_PropManager::registerProp(SKETCH_TAB_NAME, "rotate_to_plane",
"Rotate to plane when selected", Config_Prop::Boolean, "false");
GeomShapePtr aLineShape1 = aLineAttribute1->value();
ResultPtr aContext1 = aLineAttribute1->context();
if(!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if(!aLineShape1.get()) {
GeomShapePtr aShape1 = anAttribute1->value();
ResultPtr aContext1 = anAttribute1->context();
if(!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if(!aShape1.get()) {
GeomShapePtr aPointShape1 = aPointAttribute1->value();
ResultPtr aContext1 = aPointAttribute1->context();
if(!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if(!aPointShape1.get()) {
GeomShapePtr aShape1 = anAttribute1->value();
ResultPtr aContext1 = anAttribute1->context();
if(!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if(!aShape1.get()) {
GeomShapePtr aShape1 = anAttribute1->value();
ResultPtr aContext1 = anAttribute1->context();
if(!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if(!aShape1.get()) {
GeomShapePtr aShape1 = anAttribute1->value();
ResultPtr aContext1 = anAttribute1->context();
if(!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if(!aShape1.get()) {
GeomShapePtr aShape1 = anAttribute1->value();
ResultPtr aContext1 = anAttribute1->context();
if (!aContext1.get()) {
- theError = "One of the attribute not initialized.";
+ theError = "One of the attribute is not initialized.";
return false;
}
if (!aShape1.get()) {
<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>THe second point does not contain element with acceptable shape type. The type should be: %1</translation>
+ <translation>The second point does not contain element with acceptable shape type. The type should be: %1</translation>
</message>
</context>
<context>
--- /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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "coincident_point" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "line" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "plane" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "plane1" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "point1" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "edge" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "edge_for_point_projection" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "intersection_line_1" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "object_for_center_of_gravity" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "face_for_point_projection" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "intersection_line" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "intersection_plane_1" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "object_for_center_of_circle" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "face_for_point_projection" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "intersection_line" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "intersection_plane_1" is not initialized.</source>
+ <translation>AA</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>
SET(TEXT_RESOURCES
ExchangePlugin_msg_en.ts
+ ExchangePlugin_msg_fr.ts
)
SET(PROJECT_LIBRARIES
#include <GeomAlgoAPI_XAOExport.h>
#include <GeomAPI_Shape.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeString.h>
// if context is in results, return true
for(int a = 0; a < theSelection->size(); a++) {
AttributeSelectionPtr anAttr = theSelection->value(a);
- ResultBodyPtr aSelected= std::dynamic_pointer_cast<ModelAPI_ResultBody>(anAttr->context());
- if (aSelected.get() && theCashedResults.count(aSelected))
+ ResultPtr aContext = anAttr->context();
+ // check is it group selected for groups BOP
+ if (aContext.get() && aContext->groupName() == ModelAPI_ResultGroup::group()) {
+ // it is impossible by used results check which result is used in this group result,
+ // so check the results shapes is it in results of this document or not
+ FeaturePtr aSelFeature =
+ std::dynamic_pointer_cast<ModelAPI_Feature>(theSelection->owner());
+ if (!aSelFeature.get() || aSelFeature->results().empty())
+ continue;
+ GeomShapePtr aGroupResShape = aSelFeature->firstResult()->shape();
+
+ std::set<ResultPtr>::iterator allResultsIter = theCashedResults.begin();
+ for(; allResultsIter != theCashedResults.end(); allResultsIter++) {
+ GeomShapePtr aResultShape = (*allResultsIter)->shape();
+
+ GeomAPI_Shape::ShapeType aType =
+ GeomAPI_Shape::shapeTypeByStr(theSelection->selectionType());
+ GeomAPI_ShapeExplorer aGroupResExp(aGroupResShape, aType);
+ for(; aGroupResExp.more(); aGroupResExp.next()) {
+ if (aResultShape->isSubShape(aGroupResExp.current(), false))
+ return true; // at least one shape of the group is in the used results
+ }
+ }
+ }
+ ResultBodyPtr aSelected = std::dynamic_pointer_cast<ModelAPI_ResultBody>(anAttr->context());
+ if (!aSelected.get()) { // try to get selected feature and all its results
+ FeaturePtr aContextFeature = anAttr->contextFeature();
+ if (aContextFeature.get() && !aContextFeature->results().empty()) {
+ const std::list<ResultPtr>& allResluts = aContextFeature->results();
+ std::list<ResultPtr>::const_iterator aResIter = allResluts.cbegin();
+ for(; aResIter != allResluts.cend(); aResIter++) {
+ if (aResIter->get() && theCashedResults.count(*aResIter))
+ return true;
+ }
+ }
+ } else if (aSelected.get() && theCashedResults.count(aSelected))
return true;
}
return false;
for (int aGroupIndex = 0; aGroupIndex < aGroupCount; ++aGroupIndex) {
ResultGroupPtr aResultGroup = std::dynamic_pointer_cast<ModelAPI_ResultGroup>(
(*aDoc)->object(ModelAPI_ResultGroup::group(), aGroupIndex));
+ if (!aResultGroup.get() || !aResultGroup->shape().get())
+ continue;
FeaturePtr aGroupFeature = (*aDoc)->feature(aResultGroup);
// conversion of dimension
std::string aSelectionType = aSelectionList->selectionType();
+ GeomAPI_Shape::ShapeType aSelType = GeomAPI_Shape::shapeTypeByStr(aSelectionType);
std::string aDimensionString =
ExchangePlugin_Tools::selectionType2xaoDimension(aSelectionType);
XAO::Dimension aGroupDimension = XAO::XaoUtils::stringToDimension(aDimensionString);
aResultGroup->data()->name());
try {
- for (int aSelectionIndex = 0; aSelectionIndex < aSelectionList->size(); ++aSelectionIndex){
- AttributeSelectionPtr aSelection = aSelectionList->value(aSelectionIndex);
-
- // complex conversion of reference id to element index
- // gives bad id in case the selection is done from python script
- // => using GeomAlgoAPI_CompoundBuilder::id instead
- // int aReferenceID_old = aSelection->Id();
-
- int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aSelection->value());
-
+ GeomAPI_ShapeExplorer aGroupResExplorer(aResultGroup->shape(), aSelType);
+ for(; aGroupResExplorer.more(); aGroupResExplorer.next()) {
+ int aReferenceID = GeomAlgoAPI_CompoundBuilder::id(aShape, aGroupResExplorer.current());
if (aReferenceID == 0) // selected value does not found in the exported shape
continue;
-
std::string aReferenceString = XAO::XaoUtils::intToString(aReferenceID);
int anElementID =
aXao.getGeometry()->getElementIndexByReference(aGroupDimension, aReferenceString);
-
aXaoGroup->add(anElementID);
}
} catch (XAO::XAO_Exception& e) {
<name>Export:selection_list:GeomValidators_Finite</name>
<message>
<source>Infinite result is selected.</source>
- <translation>Olny finitive shapes can be exported</translation>
+ <translation>Only finitive shapes can be exported</translation>
</message>
</context>
<context>
--- /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>
helpfile="exportFeature.html">
<source path="export_widget.xml" />
</feature>
- <feature id="Dump" title="Dump" tooltip="Dump python script" icon="icons/Exchange/dump.png"
+ <feature id="Dump" title="Dump" tooltip="Dump Python script" icon="icons/Exchange/dump.png"
helpfile="dumpFeature.html">
<export_file_selector id="file_path"
type="save"
const ModelHighAPI_Selection& theTo);
/// \ingroup CPPHighAPI
-/// \brief Calculate radius of circular.
+/// \brief Calculate radius of circular edge, cylindrical surface or sphere.
FEATURESAPI_EXPORT
double measureRadius(const std::shared_ptr<ModelAPI_Document>& thePart,
const ModelHighAPI_Selection& theObject);
SET(TEXT_RESOURCES
FeaturesPlugin_msg_en.ts
+ FeaturesPlugin_msg_fr.ts
FeaturesPlugin_msg_ru.ts
)
TestExtrusionCut.py
TestExtrusionCut_BySize.py
TestExtrusionCut_ByPlanesAndOffsets.py
+ TestExtrusionCut_ByFaces.py
TestExtrusionFuse.py
TestExtrusionFuse_BySize.py
TestExtrusionFuse_ByPlanesAndOffsets.py
Test2854.py
Test2878.py
Test2971.py
+ Test3014.py
TestBooleanCommon_MultiLevelCompound_v0_1.py
TestBooleanCommon_MultiLevelCompound_v0_2.py
TestBooleanCommon_MultiLevelCompound_v20190506_1.py
void computeLength();
/// Compute minimal distance between pair of shapes
void computeDistance();
- /// Compute radius of circular edge or cylindrical face
+ /// Compute radius of circular edge, cylindrical surface or sphere.
void computeRadius();
/// Compute angle(s) between pair of edges if they are intersected
void computeAngle();
int aPartitionVersion = version();
if (aPartitionVersion < THE_PARTITION_VERSION_1) {
- // default behaviours of Partition
+ // default behaviors of Partition
if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) {
for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) {
storeResult(aBaseObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex);
keepUnusedSubsOfCompound(aFirstShape, anObjects, ObjectHierarchy(), aMakeShapeList);
if (anIt.more()) {
+ if (aResultCompound->shapeType() != GeomAPI_Shape::COMPOUND) {
+ // put the shape into compound
+ ListOfShape aShapes;
+ aShapes.push_back(aResultCompound);
+ aResultCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+ }
std::shared_ptr<GeomAlgoAPI_ShapeBuilder> aBuilder(new GeomAlgoAPI_ShapeBuilder);
for (; anIt.more(); anIt.next())
aBuilder->add(aResultCompound, anIt.current());
if(aSelectedWiresFromObjects.isBound(aWire)) {
theError =
- "Error: Objects with such wire already selected. Don't allow to select this object.";
+ "Error: Objects with this wire already selected. Don't allow to select this object.";
return false;
}
GeomValidators_ShapeType aShapeTypeValidator;
if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
theError = "Error: Selected shape has unacceptable type. Acceptable types are: faces or "
- "wires on sketch, whole sketch(if it has at least one face), "
+ "wires on sketch, whole sketch (if it has at least one face), "
"and whole objects with shape types: %1";
std::string anArgumentString;
for(auto anIt = theArguments.cbegin(); anIt != theArguments.cend(); ++anIt) {
/// \class FeaturesPlugin_ValidatorBaseForGeneration
/// \ingroup Validators
/// \brief A validator for selection base for generation. Allows to select faces on sketch,
-/// whole sketch(if it has at least one face), and following objects: vertex, edge, wire, face.
+/// whole sketch (if it has at least one face), and following objects: vertex, edge, wire, face.
class FeaturesPlugin_ValidatorBaseForGeneration: public ModelAPI_AttributeValidator
{
public:
<context>
<name>Extrusion:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>Extrusion:base :FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</translation>
</message>
</context>
<context>
<context>
<name>Extrusion:GeomValidators_ZeroOffset</name>
<message>
- <source>Wrong number of validator arguments in xml(expected 9).</source>
- <translation>Wrong number of validator arguments in xml(expected 9).</translation>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Wrong number of validator arguments in xml (expected 9).</translation>
</message>
</context>
<context>
<context>
<name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>ExtrusionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</translation>
</message>
</context>
<context>
<context>
<name>ExtrusionCut:GeomValidators_ZeroOffset</name>
<message>
- <source>Wrong number of validator arguments in xml(expected 9).</source>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
<translation></translation>
</message>
</context>
<context>
<name>Revolution:GeomValidators_ZeroOffset</name>
<message>
- <source>Wrong number of validator arguments in xml(expected 9).</source>
- <translation>Wrong number of validator "GeomValidators_ZeroOffset" arguments in xml(expected 9).</translation>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Wrong number of validator "GeomValidators_ZeroOffset" arguments in xml (expected 9).</translation>
</message>
</context>
<context>
<context>
<name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>Revolution:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</translation>
</message>
</context>
<context>
<context>
<name>RevolutionCut:GeomValidators_ZeroOffset</name>
<message>
- <source>Wrong number of validator arguments in xml(expected 9).</source>
- <translation>Wrong number of validator "GeomValidators_ZeroOffset" arguments in xml(expected 9).</translation>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Wrong number of validator "GeomValidators_ZeroOffset" arguments in xml (expected 9).</translation>
</message>
</context>
<context>
<name>RevolutionCut:Model_FeatureValidator</name>
<message>
<source>Attribute "main_objects" is not initialized.</source>
- <translation>Objects for cut is not selected.</translation>
+ <translation>Objects for cut are not selected.</translation>
</message>
</context>
<context>
<context>
<name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>RevolutionCut:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</translation>
</message>
</context>
<context>
<context>
<name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>ExtrusionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</translation>
</message>
</context>
<context>
<context>
<name>ExtrusionFuse:GeomValidators_ZeroOffset</name>
<message>
- <source>Wrong number of validator arguments in xml(expected 9).</source>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
<translation></translation>
</message>
</context>
<context>
<name>RevolutionFuse:GeomValidators_ZeroOffset</name>
<message>
- <source>Wrong number of validator arguments in xml(expected 9).</source>
- <translation>Wrong number of validator "GeomValidators_ZeroOffset" arguments in xml(expected 9).</translation>
+ <source>Wrong number of validator arguments in xml (expected 9).</source>
+ <translation>Wrong number of validator "GeomValidators_ZeroOffset" arguments in xml (expected 9).</translation>
</message>
</context>
<context>
<context>
<name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>RevolutionFuse:base:FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</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>Wrong number of validator "GeomValidators_MinObjectsSelected" arguments(expected 2): selection list id and min number of objects.</translation>
+ <translation>Wrong number of validator "GeomValidators_MinObjectsSelected" arguments (expected 2): selection list id and min number of objects.</translation>
</message>
</context>
<context>
<translation>Object for pipe path is not selected.</translation>
</message>
</context>
- <context>
- <name>Pipe:FeaturesPlugin_ValidatorPipeLocations</name>
- <message>
- <source>Error: Feature \"%1\" does not supported by this validator.</source>
- <translation>Feature "%1" does not supported validator "FeaturesPlugin_ValidatorPipeLocations".</translation>
- </message>
- </context>
<context>
<name>Pipe:FeaturesPlugin_ValidatorPipeLocations</name>
<message>
<context>
<name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
<message>
- <source>Error: Objects with such wire already selected. Don't allow to select this object.</source>
- <translation>Objects with such wire already selected. Don't allow to select this object.</translation>
+ <source>Error: Objects with this wire already selected. Don't allow to select this object.</source>
+ <translation>Objects with this wire already selected. Don't allow to select this object.</translation>
</message>
</context>
<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>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</translation>
- </message>
- </context>
- <context>
- <name>Pipe:base_objects:FeaturesPlugin_ValidatorBaseForGeneration</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
+ <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>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</translation>
</message>
</context>
<context>
<translation>Selected object has empty context.</translation>
</message>
</context>
- <context>
- <name>Remove_SubShapes:FeaturesPlugin_ValidatorRemoveSubShapesResult</name>
- <message>
- <source>Error: Feature \"%1\" does not supported by this validator.</source>
- <translation>Feature "%1" does not supported validator "FeaturesPlugin_ValidatorRemoveSubShapesResult".</translation>
- </message>
- </context>
<context>
<name>Remove_SubShapes:FeaturesPlugin_ValidatorRemoveSubShapesResult</name>
<message>
<translation></translation>
</message>
</context>
- <context>
- <name>Remove_SubShapes:base_shape:GeomValidators_BodyShapes</name>
- <message>
- <source>Error: Attribute \"%1\" does not supported by this validator.</source>
- <translation></translation>
- </message>
- </context>
<context>
<name>Remove_SubShapes:subshapes:FeaturesPlugin_ValidatorRemoveSubShapesSelection</name>
<message>
<name>Intersection:tool_objects:GeomValidators_IntersectionSelection</name>
<message>
<source>Error: empty feature.</source>
- <translation>Selected objects has empty feature.</translation>
+ <translation>Selected objects have empty feature.</translation>
</message>
</context>
<context>
<translation>Objects from the %1 group can be selected in the %2 document, but an objects from the %3 group is selected.</translation>
</message>
</context>
- <context>
- <name>Union:FeaturesPlugin_ValidatorUnionArguments</name>
- <message>
- <source>Error: This validator supports only \"%1\" feature.</source>
- <translation>This validator "FeaturesPlugin_ValidatorUnionArguments" supports only "%1" feature.</translation>
- </message>
- </context>
<context>
<name>Union:FeaturesPlugin_ValidatorUnionArguments</name>
<message>
<context>
<name>FusionFaces:Model_FeatureValidator</name>
<message>
- <source>Attribute "base_shape" is not initialized.</source >
- <translation>Base shape is not selected.</translation >
+ <source>Attribute "base_shape" is not initialized.</source>
+ <translation>Base shape is not selected.</translation>
</message>
</context>
</TS>
--- /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>
+ </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>
+ </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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>AA</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>
+ </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>
+ </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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "center_point" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <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 "to_size" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_size" is not initialized.</source>
+ <translation>AA</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 "from_offset" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_offset" is not initialized.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Extrusion:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 "to_size" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_size" is not initialized.</source>
+ <translation>AA</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 "from_offset" is not initialized.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 "to_angle" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_angle" is not initialized.</source>
+ <translation>AA</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 "from_offset" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "to_offset" is not initialized.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>Revolution:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 "to_angle" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_angle" is not initialized.</source>
+ <translation>AA</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 "from_offset" is not initialized.</source>
+ <translation>AA</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 "to_offset" is not initialized.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionCut:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 "to_size" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_size" is not initialized.</source>
+ <translation>AA</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 "from_offset" is not initialized.</source>
+ <translation>AA</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 "to_offset" is not initialized.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>ExtrusionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 "to_angle" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "from_angle" is not initialized.</source>
+ <translation>AA</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 "from_offset" is not initialized.</source>
+ <translation>AA</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 "to_offset" is not initialized.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:from_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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 face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a face.</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+ <context>
+ <name>RevolutionFuse:to_object:GeomValidators_Face</name>
+ <message>
+ <source>The shape is not a plane.</source>
+ <translation>AA</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_centering" is not initialized.</source>
+ <translation>AA</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>Placement:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "placement_reverse_direction" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "distance" is not initialized.</source>
+ <translation>AA</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>Union:GeomValidators_MinObjectsSelected</name>
+ <message>
+ <source>Error: Attribute "%1" should contain at least %2 items.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_angular" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_first_dir" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "angle_from" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "angle_point_1" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "circular" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "distance_from" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "edge_for_length" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "center_point" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "axis_object" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>AA</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:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "end_point" is not initialized.</source>
+ <translation>AA</translation>
+ </message>
+ <message>
+ <source>Attribute "main_objects" is not initialized.</source>
+ <translation>AA</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>
+ </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>
--- /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 GeomAPI import *
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "nb", "10")
+model.addParameter(Part_1_doc, "h", "20")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_1.addCircle(0, 55.86212361331221, 9.333219356250011)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.result(), SketchCircle_1.center())
+SketchMultiRotation_1 = Sketch_1.addRotation([SketchCircle_1.results()[1]], SketchAPI_Line(SketchLine_1).startPoint(), 360, "nb", True)
+[SketchCircle_2, SketchCircle_3, SketchCircle_4, SketchCircle_5, SketchCircle_6, SketchCircle_7, SketchCircle_8, SketchCircle_9, SketchCircle_10] = SketchMultiRotation_1.rotated()
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "all-in-Sketch_1")], model.selection(), "h", 0)
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "Extrusion_1_4/To_Face"), "h/2", True)
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("FACE", "Plane_1"), model.selection("COMPOUND", "all-in-Extrusion_1")], 20190506)
+model.end()
+
+assert(Partition_1.feature().error() == "")
+
+model.testNbResults(Partition_1, 1)
+model.testNbSubResults(Partition_1, [10])
+model.testNbSubShapes(Partition_1, GeomAPI_Shape.SOLID, [20])
+
+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
+#
+
+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(25, 0, 0, 0)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchPoint_1.result())
+SketchLine_2 = Sketch_1.addLine(0, 0, 0, 200)
+SketchLine_3 = Sketch_1.addLine(0, 200, 25, 200)
+SketchLine_3.setAuxiliary(True)
+SketchLine_4 = Sketch_1.addLine(25, 200, 25, 0)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_5 = 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())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 200)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_1.result(), 25)
+SketchLine_5 = Sketch_1.addLine(125, 243.301270189222, -25, 243.3012701892219)
+SketchLine_5.setAuxiliary(True)
+SketchLine_6 = Sketch_1.addLine(-25, 243.3012701892219, 0, 200)
+SketchLine_6.setAuxiliary(True)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_6.endPoint())
+SketchLine_7 = Sketch_1.addLine(0, 200, 0, 350)
+SketchLine_7.setAuxiliary(True)
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_7.startPoint())
+SketchConstraintHorizontal_3 = Sketch_1.setHorizontal(SketchLine_5.result())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_5.result(), SketchLine_7.result())
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_7.result(), SketchLine_6.result(), 30)
+SketchLine_8 = Sketch_1.addLine(-25, 243.3012701892219, 29.37846722219903, 268.6583658936639)
+SketchConstraintCoincidence_9 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_8.startPoint())
+SketchLine_9 = Sketch_1.addLine(29.37846722219903, 268.6583658936639, 14.58682806127452, 300.3791384399466)
+SketchConstraintCoincidence_10 = Sketch_1.setCoincident(SketchLine_8.endPoint(), SketchLine_9.startPoint())
+SketchConstraintPerpendicular_2 = Sketch_1.setPerpendicular(SketchLine_8.result(), SketchLine_9.result())
+SketchConstraintLength_3 = Sketch_1.setLength(SketchLine_6.result(), 50)
+SketchConstraintLength_4 = Sketch_1.setLength(SketchLine_8.result(), 60)
+SketchConstraintAngle_2 = Sketch_1.setAngle(SketchLine_5.result(), SketchLine_8.result(), 25)
+SketchConstraintLength_5 = Sketch_1.setLength(SketchLine_9.result(), 35)
+SketchLine_10 = Sketch_1.addLine(23.03919329608853, 282.2529826992136, 36.18065620811996, 288.3809474944538)
+SketchLine_10.setAuxiliary(True)
+SketchConstraintCoincidence_11 = Sketch_1.setCoincident(SketchLine_10.startPoint(), SketchLine_9.result())
+SketchLine_11 = Sketch_1.addLine(36.18065620811996, 288.3809474944538, 48.85920406034094, 261.1917138833543)
+SketchLine_11.setAuxiliary(True)
+SketchConstraintCoincidence_12 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintPerpendicular_3 = Sketch_1.setPerpendicular(SketchLine_10.result(), SketchLine_11.result())
+SketchConstraintPerpendicular_4 = Sketch_1.setPerpendicular(SketchLine_9.result(), SketchLine_10.result())
+SketchConstraintLength_6 = Sketch_1.setLength(SketchLine_11.result(), 30)
+SketchConstraintLength_7 = Sketch_1.setLength(SketchLine_10.result(), 14.5)
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_9.endPoint(), SketchLine_10.startPoint(), 20, True)
+SketchArc_1 = Sketch_1.addArc(4.697206021778518, 257.149304782984, 14.58682806127452, 300.3791384399466, 48.85920406034094, 261.1917138833543, True)
+SketchConstraintCoincidence_13 = Sketch_1.setCoincident(SketchLine_9.endPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_14 = Sketch_1.setCoincident(SketchLine_11.endPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_15 = Sketch_1.setCoincident(SketchLine_10.endPoint(), SketchArc_1.results()[1])
+SketchArc_2 = Sketch_1.addArc(0.1512256873309691, 256.7331845326764, 48.85920406034094, 261.1917138833543, 34.14802119649147, 221.5683791690064, True)
+SketchConstraintCoincidence_16 = Sketch_1.setCoincident(SketchLine_11.endPoint(), SketchArc_2.startPoint())
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_2.results()[1], SketchArc_1.results()[1])
+SketchArc_3 = Sketch_1.addArc(-71.98457930083825, 187.3071972226404, 0, 200, -25, 243.3012701892219, False)
+SketchConstraintCoincidence_17 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchArc_3.startPoint())
+SketchConstraintCoincidence_18 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchArc_3.endPoint())
+SketchLine_12 = Sketch_1.addLine(-25, 243.301270189222, 0, 222.3237794097899)
+SketchLine_12.setAuxiliary(True)
+SketchConstraintCoincidence_19 = Sketch_1.setCoincident(SketchLine_5.endPoint(), SketchLine_12.startPoint())
+SketchConstraintCoincidence_20 = Sketch_1.setCoincident(SketchLine_12.endPoint(), SketchLine_7.result())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_3.results()[1], SketchLine_12.result())
+SketchConstraintAngle_3 = Sketch_1.setAngle(SketchLine_6.result(), SketchLine_12.result(), 20)
+SketchArc_4 = Sketch_1.addArc(55, 200, 34.14802119649147, 221.5683791690064, 25, 200, False)
+SketchConstraintCoincidence_21 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchArc_4.startPoint())
+SketchConstraintTangent_3 = Sketch_1.setTangent(SketchArc_2.results()[1], SketchArc_4.results()[1])
+SketchConstraintCoincidence_22 = Sketch_1.setCoincident(SketchArc_4.endPoint(), SketchLine_4.startPoint())
+SketchConstraintTangent_4 = Sketch_1.setTangent(SketchLine_4.result(), SketchArc_4.results()[1])
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_4.results()[1], 30)
+SketchLine_13 = Sketch_1.addLine(-7.179200577043265, 240.5774662449659, 15.47849409887298, 251.1429227884834)
+SketchLine_14 = Sketch_1.addLine(15.47849409887298, 251.1429227884834, 26.04395064239047, 228.4852281125672)
+SketchConstraintCoincidence_23 = Sketch_1.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchLine_15 = Sketch_1.addLine(26.04395064239047, 228.4852281125672, 3.386255966474217, 217.9197715690497)
+SketchConstraintCoincidence_24 = Sketch_1.setCoincident(SketchLine_14.endPoint(), SketchLine_15.startPoint())
+SketchLine_16 = Sketch_1.addLine(3.386255966474217, 217.9197715690497, -7.179200577043265, 240.5774662449659)
+SketchConstraintCoincidence_25 = Sketch_1.setCoincident(SketchLine_15.endPoint(), SketchLine_16.startPoint())
+SketchConstraintCoincidence_26 = Sketch_1.setCoincident(SketchLine_13.startPoint(), SketchLine_16.endPoint())
+SketchConstraintParallel_1 = Sketch_1.setParallel(SketchLine_13.result(), SketchLine_15.result())
+SketchConstraintParallel_2 = Sketch_1.setParallel(SketchLine_16.result(), SketchLine_14.result())
+SketchConstraintPerpendicular_5 = Sketch_1.setPerpendicular(SketchLine_13.result(), SketchLine_14.result())
+SketchConstraintParallel_3 = Sketch_1.setParallel(SketchLine_13.result(), SketchLine_8.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_15.result(), SketchLine_14.result())
+SketchConstraintLength_8 = Sketch_1.setLength(SketchLine_13.result(), 25)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_8.result(), SketchLine_16.endPoint(), 10, True)
+SketchConstraintDistance_3 = Sketch_1.setDistance(SketchArc_3.endPoint(), SketchLine_16.result(), 15, True)
+SketchConstraintLength_9 = Sketch_1.setLength(SketchLine_5.result(), 150)
+SketchConstraintLength_10 = Sketch_1.setLength(SketchLine_7.result(), 150)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_4r-SketchArc_4_2r-SketchArc_2_2f-SketchArc_1_2f-SketchLine_9r-SketchLine_8r-SketchArc_3_2r-SketchLine_2r-SketchLine_1r-SketchLine_13f-SketchLine_14f-SketchLine_15f-SketchLine_16f")], model.selection(), 10, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_14"))
+SketchLine_17 = Sketch_2.addLine(-221.0712923119171, 10, -196.0712923119172, 0)
+SketchLine_17.setAuxiliary(True)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_13][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_14][Extrusion_1_1/To_Face]"), False)
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchConstraintCoincidence_27 = Sketch_2.setCoincident(SketchLine_17.startPoint(), SketchPoint_2.result())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_14][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_15][Extrusion_1_1/From_Face]"), False)
+SketchPoint_3 = SketchProjection_3.createdFeature()
+SketchConstraintCoincidence_28 = Sketch_2.setCoincident(SketchLine_17.endPoint(), SketchPoint_3.result())
+SketchCircle_1 = Sketch_2.addCircle(-208.5712923119172, 5, 4)
+SketchConstraintCoincidence_29 = Sketch_2.setCoincident(SketchLine_17.result(), SketchCircle_1.center())
+SketchConstraintMiddle_1 = Sketch_2.setMiddlePoint(SketchCircle_1.center(), SketchLine_17.result())
+SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_1.results()[1], 4)
+model.do()
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [model.selection("WIRE", "Sketch_2/Face-SketchCircle_1_2f_wire")], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_1/SketchArc_3_2"), 0, model.selection(), 5, [model.selection("SOLID", "Extrusion_1_1")])
+model.do()
+
+from GeomAPI import GeomAPI_Shape
+
+model.testNbResults(ExtrusionCut_1, 1)
+model.testNbSubResults(ExtrusionCut_1, [0])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.FACE, [18])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.EDGE, [90])
+model.testNbSubShapes(ExtrusionCut_1, GeomAPI_Shape.VERTEX, [180])
+model.testResultsVolumes(ExtrusionCut_1, [78707.15553129233])
+
+model.testHaveNamingSubshapes(ExtrusionCut_1, model, Part_1_doc)
+
+model.end()
+
+assert(model.checkPythonDump())
model.testResultsVolumes(Extrusion_1, [57985.85])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
model.testResultsVolumes(Extrusion_1, [37985.85])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testResultsVolumes(Extrusion_1, [107985.85])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [6])
model.testResultsVolumes(Extrusion_1, [87985.85])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testResultsVolumes(Extrusion_1, [119535.04])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
model.testResultsVolumes(Extrusion_1, [84126.377])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testResultsVolumes(Extrusion_1, [105008.93])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testResultsVolumes(Extrusion_1, [179594.5])
# check failure
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
assert(Extrusion_1.feature().error() != "")
model.testResultsVolumes(Extrusion_1, [7626.2279286])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [40])
model.testResultsVolumes(Extrusion_1, [21514.8965])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [31501.9671234])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [5])
model.testResultsVolumes(Extrusion_1, [18737.752452])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testResultsVolumes(Extrusion_1, [57985.85])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
model.testResultsVolumes(Extrusion_1, [37985.85])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [107985.85])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [12])
model.testResultsVolumes(Extrusion_1, [87985.85])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [119535.04])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
model.testResultsVolumes(Extrusion_1, [84126.377])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [105008.93])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [179594.5])
# check failure
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
assert(Extrusion_1.feature().error() != "")
model.testResultsVolumes(Extrusion_1, [7626.2279286])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [136])
model.testResultsVolumes(Extrusion_1, [21514.8965])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [31501.9671234])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [9])
model.testResultsVolumes(Extrusion_1, [18737.752452])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [2899.292521, 1039.2304845, 2899.292521, 1131.3708499])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 4)
model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
model.testResultsVolumes(Extrusion_1, [3899.292521, 1439.2304845, 3899.292521, 1531.3708499])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 4)
model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
model.testResultsVolumes(Extrusion_1, [5399.2925211, 2039.2304845, 5399.2925212, 2131.37085])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 4)
model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 8, 8])
model.testResultsVolumes(Extrusion_1, [6399.2925211, 2439.2304845, 6399.2925212, 2531.37085])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 4)
model.testNbSubResults(Extrusion_1, [0, 0, 0, 0])
model.testResultsVolumes(Extrusion_1, [2295.81450653, 2295.81450653, 5527.16645028])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 3)
model.testNbSubResults(Extrusion_1, [0, 0, 0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [8, 8, 12])
model.testResultsVolumes(Extrusion_1, [1595.81450653, 1595.81450653, 3814.47306888])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 3)
model.testNbSubResults(Extrusion_1, [0, 0, 0])
model.testResultsVolumes(Extrusion_1, [1708.843326299, 1708.843325768, 1895.559443038])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 3)
model.testNbSubResults(Extrusion_1, [0, 0, 0])
model.testResultsVolumes(Extrusion_1, [2915.069101129, 2915.069100598, 4138.27332218])
# check failure
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
assert(Extrusion_1.feature().error() != "")
# revert failure
-ParamFrom.setValue(10)
+ParamFrom.setValue(-10)
model.do()
model.testNbResults(Extrusion_1, 3)
model.testNbSubResults(Extrusion_1, [0, 0, 0])
model.testResultsVolumes(Extrusion_1, [1504.36096473])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [24])
model.testResultsVolumes(Extrusion_1, [4336.142699])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [2])
model.testResultsVolumes(Extrusion_1, [1314.8586588, 1022.169915122, 2601.32913399])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 3)
model.testNbSubResults(Extrusion_1, [0, 0, 0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.FACE, [1, 1, 1])
model.testResultsVolumes(Extrusion_1, [825.71966141, 533.030917699, 1551.6191757579])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 3)
model.testNbSubResults(Extrusion_1, [0, 0, 0])
model.testResultsVolumes(Extrusion_1, [7969.186376787])
# offset "From" face
-ParamFrom.setValue(-20)
+ParamFrom.setValue(20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
model.testNbSubShapes(Extrusion_1, GeomAPI_Shape.VERTEX, [32])
model.testResultsVolumes(Extrusion_1, [10769.186376787])
-ParamFrom.setValue(20)
+ParamFrom.setValue(-20)
model.do()
model.testNbResults(Extrusion_1, 1)
model.testNbSubResults(Extrusion_1, [0])
label="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."
+3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it."
shape_types="vertices edges wires faces shells solids compsolids compounds">
<validator id="FeaturesPlugin_ValidatorCompositeLauncher" parameters="base,Sketch"/>
</sketch_launcher>
label="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."
+3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it."
shape_types="wires faces shells">
<validator id="FeaturesPlugin_ValidatorCompositeLauncher" parameters="base,Sketch"/>
</sketch_launcher>
</doublevalue>
</groupbox>
</box>
- <box id="ByPlanesAndOffsets" title="By bounding planes and offsets" icon="icons/Features/plane_inverted_32x32.png">
+ <box id="ByPlanesAndOffsets" title="By bounding faces and offsets" icon="icons/Features/plane_inverted_32x32.png">
<groupbox title="From">
<shape_selector id="from_object"
icon="icons/Features/plane.png"
- label="Plane face"
- tooltip="Bounding plane (select a planar face)"
+ label="From face"
+ tooltip="From face"
shape_types="face"
geometrical_selection="true"
default="<base sketch>">
- <validator id="GeomValidators_Face" parameters="plane"/>
+ <validator id="FeaturesPlugin_ValidatorExtrusionBoundary"/>
</shape_selector>
<doublevalue id="from_offset"
label="Offset" step="1.0" default="0"
<groupbox title="To">
<shape_selector id="to_object"
icon="icons/Features/plane_inverted.png"
- label="Plane face"
- tooltip="Bounding plane (select a planar face)"
+ label="To face"
+ tooltip="To face"
shape_types="face"
geometrical_selection="true"
default="<base sketch>">
- <validator id="GeomValidators_Face" parameters="plane"/>
+ <validator id="FeaturesPlugin_ValidatorExtrusionBoundary"/>
</shape_selector>
<doublevalue id="to_offset"
label="Offset" step="1.0" default="0"
label="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."
+3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it."
shape_types="vertices edges wires faces shells compounds">
<validator id="FeaturesPlugin_ValidatorCompositeLauncher" parameters="base,Sketch"/>
</sketch_launcher>
</doublevalue>
</groupbox>
</box>
- <box id="ByPlanesAndOffsets" title="By bounding planes and offsets" icon="icons/Features/plane_inverted_32x32.png">
+ <box id="ByPlanesAndOffsets" title="By bounding faces and offsets" icon="icons/Features/plane_inverted_32x32.png">
<groupbox title="From">
<shape_selector id="from_object"
icon="icons/Features/plane.png"
- label="Plane face"
- tooltip="Bounding plane (select a planar face)"
+ label="From face"
+ tooltip="From face"
shape_types="face"
geometrical_selection="true"
default="<base sketch>">
- <validator id="GeomValidators_Face" parameters="plane"/>
+ <validator id="FeaturesPlugin_ValidatorExtrusionBoundary"/>
</shape_selector>
<doublevalue id="from_offset"
label="Offset" step="1.0" default="0"
<groupbox title="To">
<shape_selector id="to_object"
icon="icons/Features/plane_inverted.png"
- label="Plane face"
- tooltip="Bounding plane (select a planar face)"
+ label="To face"
+ tooltip="To face"
shape_types="face"
geometrical_selection="true"
default="<base sketch>">
- <validator id="GeomValidators_Face" parameters="plane"/>
+ <validator id="FeaturesPlugin_ValidatorExtrusionBoundary"/>
</shape_selector>
<doublevalue id="to_offset"
label="Offset" step="1.0" default="0"
<multi_selector id="main_objects"
label="Objects"
icon="icons/Features/cut_shape.png"
- tooltip="Select objects(compounds, compsolids, solids, shells, faces or edges)"
+ tooltip="Select objects (compounds, compsolids, solids, shells, faces or edges)"
shape_types="edges faces shells solids compsolids compounds"
use_choice="false"
concealment="true">
default="">
</shape_selector>
</box>
- <box id="Radius" title="Radius of circular" icon="icons/Features/meas_radius_32x32.png">
+ <box id="Radius" title="Radius of circular edge, cylindrical surface or sphere" icon="icons/Features/meas_radius_32x32.png">
<shape_selector id="circular"
icon=""
label="Object"
icon="icons/Features/extrusion.png" helpfile="extrusionFeature.html">
<source path="extrusion_widget.xml"/>
</feature>
- <feature id="ExtrusionCut" title="ExtrusionCut" tooltip=""
+ <feature id="ExtrusionCut" title="ExtrusionCut" tooltip="Cuts an extrusion from a solid"
icon="icons/Features/extrusion_cut.png" helpfile="extrusionCutFeature.html">
<source path="extrusioncut_widget.xml"/>
</feature>
- <feature id="ExtrusionFuse" title="ExtrusionFuse" tooltip=""
+ <feature id="ExtrusionFuse" title="ExtrusionFuse" tooltip="Fuses an extrusion with a solid"
icon="icons/Features/extrusion_fuse.png" helpfile="extrusionFuseFeature.html">
<source path="extrusionfuse_widget.xml"/>
</feature>
icon="icons/Features/revol.png" helpfile="revolutionFeature.html">
<source path="revolution_widget.xml"/>
</feature>
- <feature id="RevolutionCut" title="RevolutionCut" tooltip=""
+ <feature id="RevolutionCut" title="RevolutionCut" tooltip="Cuts a revolution from a solid"
icon="icons/Features/revol_cut.png" helpfile="revolutionCutFeature.html">
<source path="revolutioncut_widget.xml"/>
</feature>
- <feature id="RevolutionFuse" title="RevolutionFuse" tooltip=""
+ <feature id="RevolutionFuse" title="RevolutionFuse" tooltip="Fuses a revolution with a solid"
icon="icons/Features/revol_fuse.png" helpfile="revolutionFuseFeature.html">
<source path="revolutionfuse_widget.xml"/>
</feature>
label="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."
+3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it."
shape_types="vertices edges wires faces shells compounds">
<validator id="FeaturesPlugin_ValidatorCompositeLauncher" parameters="base,Sketch"/>
</sketch_launcher>
label="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."
+3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it."
shape_types="wires faces shells">
<validator id="FeaturesPlugin_ValidatorCompositeLauncher" parameters="base,Sketch"/>
</sketch_launcher>
label="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."
+3. An existing result shape of kind: wires/edge/vertices. Extrusion will be filled by it."
shape_types="vertices edges wires faces shells compounds">
<validator id="FeaturesPlugin_ValidatorCompositeLauncher" parameters="base,Sketch"/>
</sketch_launcher>
<doublevalue id="from_offset" label="Angle"
step="1.0" default="0"
icon="icons/Features/angle_up_down.png"
- tooltip="Angle for "from" for bounding plane">
+ tooltip="Angle for "from" bounding plane">
</doublevalue>
</groupbox>
<groupbox title="To">
}
}
+%typemap(in) double & (double temp) {
+ if (PyLong_Check($input)) {
+ temp = PyLong_AsLong($input);
+ $1 = &temp;
+ }
+}
+
+%typemap(argout) double & {
+ $result = PyFloat_FromDouble(*$1);
+}
+
// all supported interfaces
%include "GeomAPI_Interface.h"
if (fabs(aCoefficient-theDeflection) > Precision::Confusion()) {
isModified = true;
anAISShape->SetOwnDeviationCoefficient(theDeflection);
+ Handle(Prs3d_Drawer) aDrawer = anAISShape->DynamicHilightAttributes();
+ if (!aDrawer.IsNull()) {
+ aDrawer->SetDeviationCoefficient(theDeflection);
+ }
// redisplay is necessary here to update presentation in all modes
// Standard True flag. Displayer uses Standard False flag. If it will be changed in
// displayer, redisplay here will not be necessary. But performance should be checked.
//=================================================================================================
GeomAPI_Circ::GeomAPI_Circ(const GeomCurvePtr& theCurve)
{
- Handle(Geom_Curve) aCurve = theCurve->impl<Handle(Geom_Curve)>();
+ GeomCurvePtr anUntrimmedCurve = theCurve->basisCurve();
+ Handle(Geom_Curve) aCurve = anUntrimmedCurve->impl<Handle(Geom_Curve)>();
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve);
if (aCirc.IsNull())
throw Standard_ConstructionError("GeomAPI_Circ: Curve is not a circle");
}
+GeomAPI_Circ2d::GeomAPI_Circ2d(const double theCenterX,
+ const double theCenterY,
+ const double theRadius)
+ : GeomAPI_Interface(newCirc2d(theCenterX, theCenterY, gp::DX2d(), theRadius))
+{
+}
GeomAPI_Circ2d::GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
const std::shared_ptr<GeomAPI_Pnt2d>& theCirclePoint)
class GeomAPI_Circ2d : public GeomAPI_Interface
{
- public:
+public:
+ /// Creation of circle defined by center point and circle radius
+ GEOMAPI_EXPORT
+ GeomAPI_Circ2d(const double theCenterX, const double theCenterY, const double theRadius);
+
/// Creation of circle defined by center point and circle radius
GEOMAPI_EXPORT
GeomAPI_Circ2d(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
#include <TopoDS_Shape.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Curve.hxx>
+#include <Geom_Ellipse.hxx>
#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS.hxx>
#define MY_CURVE (*(implPtr<Handle_Geom_Curve>()))
GeomAPI_Curve::GeomAPI_Curve()
- : GeomAPI_Interface(new Handle_Geom_Curve()), myStart(0), myEnd(1)
+ : GeomAPI_Interface(new Handle_Geom_Curve()),
+ myStart(-Precision::Infinite()),
+ myEnd(Precision::Infinite())
{
}
return MY_CURVE.IsNull() == Standard_True;
}
+static bool isCurveType(const Handle(Geom_Curve)& theCurve, const Handle(Standard_Type)& theType)
+{
+ if (theCurve.IsNull())
+ return false;
+ Handle(Geom_Curve) aCurve = theCurve;
+ if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+ aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
+ return aCurve->DynamicType() == theType;
+}
+
bool GeomAPI_Curve::isLine() const
{
- return !isNull() && MY_CURVE->DynamicType() == STANDARD_TYPE(Geom_Line);
+ return isCurveType(MY_CURVE, STANDARD_TYPE(Geom_Line));
}
bool GeomAPI_Curve::isCircle() const
{
- return !isNull() && MY_CURVE->DynamicType() == STANDARD_TYPE(Geom_Circle);
+ return isCurveType(MY_CURVE, STANDARD_TYPE(Geom_Circle));
+}
+
+bool GeomAPI_Curve::isEllipse() const
+{
+ return isCurveType(MY_CURVE, STANDARD_TYPE(Geom_Ellipse));
+}
+
+double GeomAPI_Curve::startParam()
+{
+ if (Precision::IsInfinite(myStart)) {
+ if (isTrimmed()) {
+ myStart = Handle(Geom_TrimmedCurve)::DownCast(MY_CURVE)->FirstParameter();
+ }
+ else if (MY_CURVE->IsClosed() && MY_CURVE->IsPeriodic())
+ myStart = 0.0;
+ }
+ return myStart;
+}
+
+double GeomAPI_Curve::endParam()
+{
+ if (Precision::IsInfinite(myEnd)) {
+ if (isTrimmed()) {
+ myEnd = Handle(Geom_TrimmedCurve)::DownCast(MY_CURVE)->LastParameter();
+ }
+ else if (MY_CURVE->IsClosed() && MY_CURVE->IsPeriodic())
+ myEnd = MY_CURVE->Period();
+ }
+ return myEnd;
}
std::shared_ptr<GeomAPI_Pnt> GeomAPI_Curve::getPoint(double theParam)
return !isNull() && MY_CURVE->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve);
}
-// unused in the unit tests for now
-// LCOV_EXCL_START
GeomCurvePtr GeomAPI_Curve::basisCurve() const
{
Handle(Geom_Curve) aCurve = MY_CURVE;
aNewCurve->setImpl(new Handle(Geom_Curve)(aCurve));
return aNewCurve;
}
-// LCOV_EXCL_STOP
+
+
+const std::shared_ptr<GeomAPI_Pnt> GeomAPI_Curve::project(
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint) const
+{
+ std::shared_ptr<GeomAPI_Pnt> aResult;
+ if (MY_CURVE.IsNull())
+ return aResult;
+
+ const gp_Pnt& aPoint = thePoint->impl<gp_Pnt>();
+
+ GeomAPI_ProjectPointOnCurve aProj(aPoint, MY_CURVE);
+ Standard_Integer aNbPoint = aProj.NbPoints();
+ if (aNbPoint > 0) {
+ gp_Pnt aNearest = aProj.NearestPoint();
+ aResult = GeomPointPtr(new GeomAPI_Pnt(aNearest.X(), aNearest.Y(), aNearest.Z()));
+ }
+ return aResult;
+}
// ================================================================================================
GEOMAPI_EXPORT
virtual bool isCircle() const;
+ /// Returns whether the curve is elliptic
+ GEOMAPI_EXPORT
+ virtual bool isEllipse() const;
+
/// Returns start parameter of the curve
GEOMAPI_EXPORT
- double startParam() const { return myStart; }
+ double startParam();
/// Returns end parameter of the curve
GEOMAPI_EXPORT
- double endParam() const { return myEnd; }
+ double endParam();
/// Returns \c true if the curve is trimmed
GEOMAPI_EXPORT
GEOMAPI_EXPORT
std::shared_ptr<GeomAPI_Pnt> getPoint(double theParam);
+ /// Project point on curve
+ GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt> project(
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint) const;
+
public:
/// \brief Compare addresses of curves
class Comparator
double angle(const std::shared_ptr<GeomAPI_Dir2d>& theArg) const;
};
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Dir2d> GeomDir2dPtr;
+
#endif
#include "GeomAPI_Ellipse.h"
#include "GeomAPI_Ax2.h"
+#include "GeomAPI_Curve.h"
#include "GeomAPI_Pnt.h"
+#include <Geom_Ellipse.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <GeomLib_Tool.hxx>
#include <gp_Elips.hxx>
#define MY_ELIPS implPtr<gp_Elips>()
{
}
+GeomAPI_Ellipse::GeomAPI_Ellipse(GeomCurvePtr theCurve)
+{
+ GeomCurvePtr anUntrimmedCurve = theCurve->basisCurve();
+ Handle(Geom_Curve) aCurve = anUntrimmedCurve->impl<Handle(Geom_Curve)>();
+ Handle(Geom_Ellipse) anEllipse = Handle(Geom_Ellipse)::DownCast(aCurve);
+ if (anEllipse.IsNull())
+ throw Standard_ConstructionError("GeomAPI_Ellipse: Curve is not an ellipse");
+ setImpl(new gp_Elips(anEllipse->Elips()));
+}
+
std::shared_ptr<GeomAPI_Pnt> GeomAPI_Ellipse::center() const
{
const gp_Pnt& aCenter = MY_ELIPS->Location();
{
return MY_ELIPS->MajorRadius();
}
+
+const std::shared_ptr<GeomAPI_Pnt> GeomAPI_Ellipse::project(
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint) const
+{
+ std::shared_ptr<GeomAPI_Pnt> aResult;
+ if (!MY_ELIPS)
+ return aResult;
+
+ Handle(Geom_Ellipse) aEllipse = new Geom_Ellipse(*MY_ELIPS);
+
+ const gp_Pnt& aPoint = thePoint->impl<gp_Pnt>();
+
+ GeomAPI_ProjectPointOnCurve aProj(aPoint, aEllipse);
+ Standard_Integer aNbPoint = aProj.NbPoints();
+ if (aNbPoint > 0) {
+ gp_Pnt aNearest = aProj.NearestPoint();
+ aResult = GeomPointPtr(new GeomAPI_Pnt(aNearest.X(), aNearest.Y(), aNearest.Z()));
+ }
+ return aResult;
+}
+
+const bool GeomAPI_Ellipse::parameter(const std::shared_ptr<GeomAPI_Pnt> thePoint,
+ const double theTolerance,
+ double& theParameter) const
+{
+ Handle(Geom_Ellipse) aCurve = new Geom_Ellipse(*MY_ELIPS);
+ return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt>(),
+ theTolerance, theParameter) == Standard_True;
+}
#include <memory>
class GeomAPI_Ax2;
+class GeomAPI_Curve;
class GeomAPI_Dir;
class GeomAPI_Pnt;
GEOMAPI_EXPORT GeomAPI_Ellipse(const std::shared_ptr<GeomAPI_Ax2>& theAx2,
double theMajorRadius, double theMinorRadius);
+ GEOMAPI_EXPORT GeomAPI_Ellipse(std::shared_ptr<GeomAPI_Curve> theCurve);
+
/// Returns center of the ellipse
GEOMAPI_EXPORT std::shared_ptr<GeomAPI_Pnt> center() const;
/// Returns major radius of the ellipse
GEOMAPI_EXPORT double majorRadius() const;
+ /// Project point on ellipse
+ GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt> project(
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint) const;
+
+ /** \brief Computes the parameter of a given point on an ellipse. The point must be
+ * located either on the circle itself or relatively to the latter
+ * at a distance less than the tolerance value. Return FALSE if the point
+ * is beyond the tolerance limit or if computation fails.
+ * Max Tolerance value is currently limited to 1.e-4
+ * \param[in] thePoint point of origin.
+ * \param[in] theTolerance tolerance of computation.
+ * \param[out] theParameter resulting parameter.
+ */
+ GEOMAPI_EXPORT const bool parameter(const std::shared_ptr<GeomAPI_Pnt> thePoint,
+ const double theTolerance,
+ double& theParameter) const;
};
//! Pointer on the object
// Author: Artem ZHIDKOV
#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Circ2d.h>
#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Lin2d.h>
#include <GeomAPI_Pnt2d.h>
+#include <Extrema_ExtCC2d.hxx>
+#include <Extrema_ExtElC2d.hxx>
+#include <Geom2d_Ellipse.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2dAPI_ProjectPointOnCurve.hxx>
+#include <GeomLib_Tool.hxx>
#include <gp_Ax22d.hxx>
#include <gp_Elips2d.hxx>
+#include <IntAna2d_AnaIntersection.hxx>
+#include <IntAna2d_Conic.hxx>
#include <Precision.hxx>
#define MY_ELLIPSE implPtr<gp_Elips2d>()
{
return MY_ELLIPSE->MajorRadius();
}
+
+// theArrangePoint is used to select the nearest solution point if intersection is detected
+template <typename EXTREMAPTR>
+static double extrema(IntAna2d_AnaIntersection* theIntersectionAlgo,
+ EXTREMAPTR theExtremaAlgo,
+ GeomPnt2dPtr theArrangePoint,
+ GeomPnt2dPtr& thePoint1,
+ GeomPnt2dPtr& thePoint2)
+{
+ double aDistance = Precision::Infinite();
+ if (theIntersectionAlgo->IsDone() && theIntersectionAlgo->NbPoints() > 0) {
+ gp_Pnt2d anArrangePoint(theArrangePoint->x(), theArrangePoint->y());
+ gp_Pnt2d anInterPnt = theIntersectionAlgo->Point(1).Value();
+ aDistance = anArrangePoint.SquareDistance(anInterPnt);
+ int aNbMergedPoints = 1;
+ // get solution nearest to theArrangePoint,
+ // if there are several point near each other, calculate average coordinates
+ for (int i = 2; i <= theIntersectionAlgo->NbPoints(); ++i) {
+ const IntAna2d_IntPoint& aPnt = theIntersectionAlgo->Point(i);
+ double aSqDist = aPnt.Value().SquareDistance(anArrangePoint);
+ if (aSqDist - aDistance < -Precision::Confusion() * aDistance) {
+ aDistance = aSqDist;
+ anInterPnt = aPnt.Value();
+ aNbMergedPoints = 1;
+ } else if (aSqDist - aDistance < Precision::Confusion() * aDistance) {
+ anInterPnt.ChangeCoord() =
+ (anInterPnt.XY() * aNbMergedPoints + aPnt.Value().XY()) / (aNbMergedPoints + 1);
+ ++aNbMergedPoints;
+ }
+ }
+
+ aDistance = 0.0; // curves are intersected
+ thePoint1 = GeomPnt2dPtr(new GeomAPI_Pnt2d(anInterPnt.X(), anInterPnt.Y()));
+ thePoint2 = GeomPnt2dPtr(new GeomAPI_Pnt2d(anInterPnt.X(), anInterPnt.Y()));
+ }
+ else if (theExtremaAlgo->IsDone() && theExtremaAlgo->NbExt() > 0) {
+ Extrema_POnCurv2d aP1, aP2;
+ for (int i = 1; i <= theExtremaAlgo->NbExt(); ++i) {
+ double aSqDist = theExtremaAlgo->SquareDistance(i);
+ if (aSqDist < aDistance) {
+ aDistance = aSqDist;
+ theExtremaAlgo->Points(i, aP1, aP2);
+ }
+ }
+ aDistance = Sqrt(aDistance);
+ thePoint1 = GeomPnt2dPtr(new GeomAPI_Pnt2d(aP1.Value().X(), aP1.Value().Y()));
+ thePoint2 = GeomPnt2dPtr(new GeomAPI_Pnt2d(aP2.Value().X(), aP2.Value().Y()));
+ }
+ return aDistance;
+}
+
+double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Lin2d>& theLine,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnLine)
+{
+ IntAna2d_AnaIntersection anInter(theLine->impl<gp_Lin2d>(), IntAna2d_Conic(*MY_ELLIPSE));
+ Extrema_ExtElC2d anExtema(theLine->impl<gp_Lin2d>(), *MY_ELLIPSE);
+ return extrema(&anInter, &anExtema, theLine->location(), thePointOnLine, thePointOnMe);
+}
+
+double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Circ2d>& theCircle,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnCircle)
+{
+ IntAna2d_AnaIntersection anInter(theCircle->impl<gp_Circ2d>(), IntAna2d_Conic(*MY_ELLIPSE));
+ Extrema_ExtElC2d anExtema(theCircle->impl<gp_Circ2d>(), *MY_ELLIPSE);
+ return extrema(&anInter, &anExtema, firstFocus(), thePointOnCircle, thePointOnMe);
+}
+
+double GeomAPI_Ellipse2d::distance(const std::shared_ptr<GeomAPI_Ellipse2d>& theEllipse,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnEllipse)
+{
+ Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(theEllipse->impl<gp_Elips2d>());
+ Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(*MY_ELLIPSE);
+
+ IntAna2d_AnaIntersection anInter(theEllipse->impl<gp_Elips2d>(), IntAna2d_Conic(*MY_ELLIPSE));
+ Extrema_ExtCC2d* anExtema =
+ new Extrema_ExtCC2d(Geom2dAdaptor_Curve(anEllipse1), Geom2dAdaptor_Curve(anEllipse2));
+ double aDistance = extrema(&anInter, anExtema, theEllipse->firstFocus(),
+ thePointOnEllipse, thePointOnMe);
+ delete anExtema;
+ return aDistance;
+}
+
+const std::shared_ptr<GeomAPI_Pnt2d> GeomAPI_Ellipse2d::project(
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const
+{
+ std::shared_ptr<GeomAPI_Pnt2d> aResult;
+ if (!MY_ELLIPSE)
+ return aResult;
+
+ Handle(Geom2d_Ellipse) aEllipse = new Geom2d_Ellipse(*MY_ELLIPSE);
+
+ const gp_Pnt2d& aPoint = thePoint->impl<gp_Pnt2d>();
+
+ Geom2dAPI_ProjectPointOnCurve aProj(aPoint, aEllipse);
+ Standard_Integer aNbPoint = aProj.NbPoints();
+ if (aNbPoint > 0) {
+ gp_Pnt2d aNearest = aProj.NearestPoint();
+ aResult.reset(new GeomAPI_Pnt2d(aNearest.X(), aNearest.Y()));
+ }
+ return aResult;
+}
+
+const bool GeomAPI_Ellipse2d::parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
+ const double theTolerance,
+ double& theParameter) const
+{
+ Handle(Geom2d_Ellipse) aCurve = new Geom2d_Ellipse(*MY_ELLIPSE);
+ return GeomLib_Tool::Parameter(aCurve, thePoint->impl<gp_Pnt2d>(),
+ theTolerance, theParameter) == Standard_True;
+}
#include <GeomAPI_Interface.h>
-class GeomAPI_Pnt2d;
+class GeomAPI_Circ2d;
class GeomAPI_Dir2d;
+class GeomAPI_Lin2d;
+class GeomAPI_Pnt2d;
/**\class GeomAPI_Ellipse2d
* \ingroup DataModel
/// Returns major radius of the ellipse
GEOMAPI_EXPORT double majorRadius() const;
+
+ /// Project point on ellipse
+ GEOMAPI_EXPORT const std::shared_ptr<GeomAPI_Pnt2d> project(
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint) const;
+
+ /** \brief Computes the parameter of a given point on an ellipse. The point must be
+ * located either on the circle itself or relatively to the latter
+ * at a distance less than the tolerance value. Return FALSE if the point
+ * is beyond the tolerance limit or if computation fails.
+ * Max Tolerance value is currently limited to 1.e-4
+ * \param[in] thePoint point of origin.
+ * \param[in] theTolerance tolerance of computation.
+ * \param[out] theParameter resulting parameter.
+ */
+ GEOMAPI_EXPORT const bool parameter(const std::shared_ptr<GeomAPI_Pnt2d> thePoint,
+ const double theTolerance,
+ double& theParameter) const;
+
+ /// Calculate minimal distance between the ellipse and a line.
+ /// Return corresponding points on the ellipse and on the line.
+ GEOMAPI_EXPORT double distance(const std::shared_ptr<GeomAPI_Lin2d>& theLine,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnLine);
+
+ /// Calculate minimal distance between the ellipse and a circle.
+ /// Return corresponding points on the ellipse and on the circle.
+ GEOMAPI_EXPORT double distance(const std::shared_ptr<GeomAPI_Circ2d>& theCircle,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnCircle);
+
+ /// Calculate minimal distance between two ellipses.
+ /// Return corresponding points on the ellipses.
+ GEOMAPI_EXPORT double distance(const std::shared_ptr<GeomAPI_Ellipse2d>& theEllipse,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnMe,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePointOnEllipse);
};
#endif
#include <Geom_SphericalSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_CylindricalSurface.hxx>
+#include <Geom_OffsetSurface.hxx>
+#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_SweptSurface.hxx>
#include <Geom_ToroidalSurface.hxx>
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
if (aSurf.IsNull())
return aResult; // no surface
- GeomLib_IsPlanarSurface isPlanar(aSurf);
- if(!isPlanar.IsPlanar()) {
- return aResult;
+ GeomLib_IsPlanarSurface isPlanarSurf(aSurf);
+ gp_Pln aPln;
+ bool isPlanar = false;
+ if (isPlanarSurf.IsPlanar()) {
+ aPln = isPlanarSurf.Plan();
+ isPlanar = true;
}
- gp_Pln aPln = isPlanar.Plan();
- double aA, aB, aC, aD;
- aPln.Coefficients(aA, aB, aC, aD);
- if (aFace.Orientation() == TopAbs_REVERSED) {
- aA = -aA;
- aB = -aB;
- aC = -aC;
- aD = -aD;
+ else if (aSurf->IsKind(STANDARD_TYPE(Geom_OffsetSurface))) {
+ Handle(Geom_OffsetSurface) anOffsetSurf = Handle(Geom_OffsetSurface)::DownCast(aSurf);
+ Handle(Geom_Surface) aBasisSurf = anOffsetSurf->BasisSurface();
+ if (aBasisSurf->IsKind(STANDARD_TYPE(Geom_Plane))) {
+ aPln = Handle(Geom_Plane)::DownCast(aBasisSurf)->Pln();
+ gp_Vec aTranslation(aPln.Axis().Direction().XYZ() * anOffsetSurf->Offset());
+ aPln.Translate(aTranslation);
+ isPlanar = true;
+ }
+ }
+
+ if (isPlanar) {
+ double aA, aB, aC, aD;
+ aPln.Coefficients(aA, aB, aC, aD);
+ if (aFace.Orientation() == TopAbs_REVERSED) {
+ aA = -aA;
+ aB = -aB;
+ aC = -aC;
+ aD = -aD;
+ }
+ aResult = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
}
- aResult = std::shared_ptr<GeomAPI_Pln>(new GeomAPI_Pln(aA, aB, aC, aD));
return aResult;
}
std::shared_ptr<GeomAPI_Pnt2d> shiftedLocation(double theShift) const;
};
+
+//! Pointer on the object
+typedef std::shared_ptr<GeomAPI_Lin2d> GeomLine2dPtr;
+
#endif
GeomAlgoAPI_Offset.cpp
GeomAlgoAPI_SolidClassifier.cpp
GeomAlgoAPI_MapShapesAndAncestors.cpp
+ GeomAlgoAPI_Projection.cpp
GeomAlgoAPI_Chamfer.cpp
)
#include <BRep_Tool.hxx>
#include <ElCLib.hxx>
+#include <GccAna_Circ2d2TanOn.hxx>
#include <GccAna_Circ2d2TanRad.hxx>
#include <GccAna_Circ2d3Tan.hxx>
#include <GccAna_Circ2dTanCen.hxx>
// Provide different mechanisms to create circle:
// * by passing points
// * by tangent edges
+// * by transversal line
// * with specified radius
// * etc.
class CircleBuilder
}
}
+ void setTransversalLine(const std::shared_ptr<GeomAPI_Shape>& theLine)
+ {
+ if (!theLine)
+ return;
+
+ const TopoDS_Edge& anEdge = TopoDS::Edge(theLine->impl<TopoDS_Shape>());
+
+ double aFirst, aLast;
+ TopLoc_Location aLoc;
+ Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, myPlane, aLoc, aFirst, aLast);
+ myTransversalLine = CurveAdaptorPtr(new Geom2dAdaptor_Curve(aCurve, aFirst, aLast));
+ }
+
void setPassingPoints(const std::vector< std::shared_ptr<GeomAPI_Pnt2d> >& thePoints)
{
std::vector< std::shared_ptr<GeomAPI_Pnt2d> >::const_iterator aPIt;
case 1:
aResult = circleByPointAndTwoTangentCurves();
break;
- case 2:
- aResult = circleByTwoPointsAndTangentCurve();
+ case 2: {
+ if (myTransversalLine)
+ aResult = circleByTwoPointsAndTransversalLine();
+ else
+ aResult = circleByTwoPointsAndTangentCurve();
break;
+ }
case 3:
aResult = circleByThreePassingPoints();
break;
}
+ Circ2dPtr circleByTwoPointsAndTransversalLine()
+ {
+ const gp_Pnt2d& aPoint1 = myPassingPoints[0];
+ const gp_Pnt2d& aPoint2 = myPassingPoints[1];
+
+ if (myTransversalLine && myTransversalLine->GetType() == GeomAbs_Line) {
+ GccAna_Circ2d2TanOn aCircleBuilder(aPoint1, aPoint2, myTransversalLine->Line(),
+ Precision::Confusion());
+ if (aCircleBuilder.NbSolutions() > 0)
+ return Circ2dPtr(new gp_Circ2d(aCircleBuilder.ThisSolution(1)));
+ }
+
+ return Circ2dPtr();
+ }
+
+
Circ2dPtr circleByRadiusAndTwoTangentCurves()
{
VectorOfGccCirc aTgCirc;
std::shared_ptr<GeomAPI_Pnt2d> myCenter;
std::vector<gp_Pnt2d> myPassingPoints;
std::vector<CurveAdaptorPtr> myTangentShapes;
+ CurveAdaptorPtr myTransversalLine;
double myRadius;
std::shared_ptr<GeomAPI_Pnt2d> myClosestPoint;
};
myTangentShapes.push_back(theEdge);
}
+void GeomAlgoAPI_Circ2dBuilder::setTransversalLine(const std::shared_ptr<GeomAPI_Shape>& theEdge)
+{
+ if (theEdge->isEdge())
+ myTransversalLine = theEdge;
+}
+
void GeomAlgoAPI_Circ2dBuilder::addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint)
{
myPassingPoints.push_back(thePoint);
CircleBuilder aCircleBuilder(myPlane);
aCircleBuilder.setCenter(myCenter);
aCircleBuilder.setTangentCurves(myTangentShapes);
+ aCircleBuilder.setTransversalLine(myTransversalLine);
aCircleBuilder.setPassingPoints(myPassingPoints);
aCircleBuilder.setClosestPoint(myClosestPoint);
aCircleBuilder.setRadius(myRadius);
GEOMALGOAPI_EXPORT
void addTangentCurve(const std::shared_ptr<GeomAPI_Shape>& theEdge);
+ /// \brief Constrain circle to be orthogonal to the given edge
+ GEOMALGOAPI_EXPORT
+ void setTransversalLine(const std::shared_ptr<GeomAPI_Shape>& theEdge);
+
/// \brief Constrain circle to pass through the given point
GEOMALGOAPI_EXPORT
void addPassingPoint(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
std::shared_ptr<GeomAPI_Pnt2d> myCenter;
std::vector< std::shared_ptr<GeomAPI_Pnt2d> > myPassingPoints;
std::vector< std::shared_ptr<GeomAPI_Shape> > myTangentShapes;
+ std::shared_ptr<GeomAPI_Shape> myTransversalLine;
std::shared_ptr<GeomAPI_Pnt2d> myClosestPoint;
double myRadius;
};
//
#include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Ax2.h>
+#include <GeomAPI_Ellipse.h>
+
#include <gp_Pln.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <TopoDS_Edge.hxx>
aRes->setImpl(new TopoDS_Shape(anEdge));
return aRes;
}
+
+std::shared_ptr<GeomAPI_Edge> GeomAlgoAPI_EdgeBuilder::ellipticArc(
+ const std::shared_ptr<GeomAPI_Pnt>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir>& theNormal,
+ const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
+ const double theMajorRadius,
+ const double theMinorRadius,
+ const std::shared_ptr<GeomAPI_Pnt>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt>& theEnd)
+{
+ std::shared_ptr<GeomAPI_Ax2> anAx2(new GeomAPI_Ax2(theCenter, theNormal, theMajorAxis));
+ GeomAPI_Ellipse anEllipse(anAx2, theMajorRadius, theMinorRadius);
+
+ GeomPointPtr aStartPnt = anEllipse.project(theStart);
+ GeomPointPtr aEndPnt = anEllipse.project(theEnd);
+
+ double aStartParam, aEndParam;
+ anEllipse.parameter(aStartPnt, Precision::Confusion(), aStartParam);
+ anEllipse.parameter(aEndPnt, Precision::Confusion(), aEndParam);
+
+ BRepBuilderAPI_MakeEdge anEdgeBuilder(anEllipse.impl<gp_Elips>(), aStartParam, aEndParam);
+ GeomEdgePtr aRes(new GeomAPI_Edge);
+ TopoDS_Edge anEdge = anEdgeBuilder.Edge();
+ aRes->setImpl(new TopoDS_Shape(anEdge));
+ return aRes;
+}
const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
const double theMajorRadius,
const double theMinorRadius);
+
+
+ /// Creates elliptic edge
+ static std::shared_ptr<GeomAPI_Edge> ellipticArc(
+ const std::shared_ptr<GeomAPI_Pnt>& theCenter,
+ const std::shared_ptr<GeomAPI_Dir>& theNormal,
+ const std::shared_ptr<GeomAPI_Dir>& theMajorAxis,
+ const double theMajorRadius,
+ const double theMinorRadius,
+ const std::shared_ptr<GeomAPI_Pnt>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt>& theEnd);
};
#endif
anOperation->SetCheckInverted(true);
anOperation->PerformWithFiller(*aDSFiller); // it references a filler fields, so keep the filler
+ myFiller = 0;
if(anOperation->HasErrors()) {
return;
}
gp_Vec anExtVec = theDirection->impl<gp_Dir>();
// Moving prism bounding faces according to "from" and "to" sizes.
- GeomShapePtr aBoundingFromShape = buildOffset(theFromShape, theFromSize, theDirection, *this);
+ GeomShapePtr aBoundingFromShape = buildOffset(theFromShape, -theFromSize, theDirection, *this);
GeomShapePtr aBoundingToShape = buildOffset(theToShape, theToSize, theDirection, *this);
// Bounding box for shapes used in prism building.
--- /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
+//
+
+#include <GeomAlgoAPI_Projection.h>
+
+#include <GeomAPI_Curve.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Pln.h>
+
+#include <Geom_Curve.hxx>
+#include <Geom_Plane.hxx>
+#include <GeomProjLib.hxx>
+
+#include <BRep_Tool.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+
+GeomAlgoAPI_Projection::GeomAlgoAPI_Projection(const GeomPlanePtr& thePlane)
+ : myPlane(thePlane)
+{
+}
+
+GeomCurvePtr GeomAlgoAPI_Projection::project(const GeomCurvePtr& theCurve)
+{
+ Handle(Geom_Curve) aCurve = theCurve->impl<Handle_Geom_Curve>();
+ Handle(Geom_Plane) aPlane = new Geom_Plane(myPlane->impl<gp_Ax3>());
+
+ Handle(Geom_Curve) aProj = GeomProjLib::Project(aCurve, aPlane);
+
+ GeomCurvePtr aProjCurve(new GeomAPI_Curve);
+ aProjCurve->setImpl(new Handle_Geom_Curve(aProj));
+ return aProjCurve;
+}
+
+GeomCurvePtr GeomAlgoAPI_Projection::project(const GeomEdgePtr& theEdge)
+{
+ GeomCurvePtr aCurve(new GeomAPI_Curve);
+
+ const TopoDS_Shape& aShape = theEdge->impl<TopoDS_Shape>();
+ TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+ if (!anEdge.IsNull()) {
+ double aStart, aEnd;
+ Handle(Geom_Curve) anEdgeCurve = BRep_Tool::Curve(anEdge, aStart, aEnd);
+ if (!anEdgeCurve.IsNull() && !BRep_Tool::IsClosed(anEdge))
+ anEdgeCurve = new Geom_TrimmedCurve(anEdgeCurve, aStart, aEnd);
+ aCurve->setImpl(new Handle_Geom_Curve(anEdgeCurve));
+ }
+
+ return project(aCurve);
+}
--- /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
+//
+
+#ifndef GeomAlgoAPI_Projection_H_
+#define GeomAlgoAPI_Projection_H_
+
+#include <GeomAlgoAPI.h>
+
+#include <GeomAPI_Pln.h>
+
+#include <memory>
+
+class GeomAPI_Curve;
+class GeomAPI_Edge;
+
+/**\class GeomAlgoAPI_Projection
+ * \ingroup DataAlgo
+ * \brief Project curve onto a plane
+ */
+class GeomAlgoAPI_Projection
+{
+public:
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_Projection(const std::shared_ptr<GeomAPI_Pln>& thePlane);
+
+ /// Project curve to the plane
+ GEOMALGOAPI_EXPORT
+ std::shared_ptr<GeomAPI_Curve> project(const std::shared_ptr<GeomAPI_Curve>& theCurve);
+ /// Project edge to the plane
+ GEOMALGOAPI_EXPORT
+ std::shared_ptr<GeomAPI_Curve> project(const std::shared_ptr<GeomAPI_Edge>& theEdge);
+
+private:
+ std::shared_ptr<GeomAPI_Pln> myPlane;
+};
+
+#endif
}
try {
+ XAO::BrepGeometry* aGeometry = dynamic_cast<XAO::BrepGeometry*>(theXao->getGeometry());
+ TopoDS_Shape aShape = aGeometry->getTopoDS_Shape();
+ bool aWasFree = aShape.Free(); // make top level topology free, same as imported
+ if (!aWasFree)
+ aShape.Free(Standard_True);
XAO::XaoExporter::saveToFile(theXao, theFileName, "");
+ if (!aWasFree)
+ aShape.Free(Standard_False);
} catch (XAO::XAO_Exception& e) {
theError = e.what();
return false;
{
// LCOV_EXCL_START
if(theArguments.size() != 9) {
- theError = "Wrong number of validator arguments in xml(expected 9).";
+ theError = "Wrong number of validator arguments in xml (expected 9).";
return false;
}
// LCOV_EXCL_STOP
myIsInitialized = myLab.FindAttribute(TDataStd_IntegerArray::GetID(), myArray) == Standard_True;
}
// checking the validity because attribute (as a field) may be presented,
- // but without label: it is undoed
+ // but without label: it is undone
return (myArray.IsNull() || !myArray->IsValid()) ? 0 : myArray->Length();
}
}
} else { // reset the old array
if (theSize) {
- if (theSize != myArray->Length()) { // old data is not keept, a new array is created
+ 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);
#include <TDF_ChildIDIterator.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
+#include <Geom_TrimmedCurve.hxx>
#include <BRep_Builder.hxx>
//#define DEB_NAMING 1
}
}
-// returns the center of the edge: circular or elliptical
+// returns the center of the edge: circular or elliptic
GeomShapePtr centerByEdge(GeomShapePtr theEdge, ModelAPI_AttributeSelection::CenterType theType)
{
if (theType != ModelAPI_AttributeSelection::NOT_CENTER && theEdge.get() != NULL) {
TopoDS_Vertex aVertex;
BRep_Builder aBuilder;
if (theType == ModelAPI_AttributeSelection::CIRCLE_CENTER) {
+ while(!aCurve.IsNull() && aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+ aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(aCurve);
if (!aCirc.IsNull()) {
aBuilder.MakeVertex(aVertex, aCirc->Location(), Precision::Confusion());
}
} else { // ellipse
+ while(!aCurve.IsNull() && aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
+ aCurve = Handle(Geom_TrimmedCurve)::DownCast(aCurve)->BasisCurve();
Handle(Geom_Ellipse) anEll = Handle(Geom_Ellipse)::DownCast(aCurve);
if (!anEll.IsNull()) {
aBuilder.MakeVertex(aVertex,
if (aCont->groupName() == ModelAPI_ResultPart::group()) {
ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aCont);
int anIndex;
- GeomShapePtr aValue = value();
- if (aValue.get())
- return aPart->data()->name() + "/" + aPart->nameInPart(aValue, anIndex);
- else
- return aPart->data()->name();
+ std::string aResult = aSubSh.get() ?
+ aPart->data()->name() + "/" + aPart->nameInPart(aSubSh, anIndex) : aPart->data()->name();
+ if (aCenterType != NOT_CENTER)
+ aResult += centersMap()[aCenterType];
+ return aResult;
}
-
// whole infinitive construction
if (aCont->groupName() == ModelAPI_ResultConstruction::group()) {
ResultConstructionPtr aConstr = std::dynamic_pointer_cast<Model_ResultConstruction>(aCont);
}
}
+
+void Model_AttributeSelection::concealedFeature(
+ const FeaturePtr theFeature, const FeaturePtr theStop, std::list<FeaturePtr>& theConcealers)
+{
+ std::set<FeaturePtr> alreadyProcessed;
+ alreadyProcessed.insert(theFeature);
+ if (theStop.get())
+ alreadyProcessed.insert(theStop);
+ /// iterate all results to find the concealment-attribute
+ const std::list<ResultPtr>& aRootRes = theFeature->results();
+ std::list<ResultPtr>::const_iterator aRootIter = aRootRes.cbegin();
+ for(; aRootIter != aRootRes.cend(); aRootIter++) {
+ std::list<ResultPtr> allRes;
+ allRes.push_back(*aRootIter);
+ ResultBodyPtr aRootBody = ModelAPI_Tools::bodyOwner(*aRootIter, true);
+ if (!aRootBody.get())
+ aRootBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRootIter);
+ if (aRootBody.get()) {
+ ModelAPI_Tools::allSubs(aRootBody, allRes);
+ }
+ for(std::list<ResultPtr>::iterator aRIter = allRes.begin(); aRIter != allRes.end(); aRIter++) {
+ const std::set<AttributePtr>& aRefs = (*aRIter)->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aRef = aRefs.cbegin();
+ for (; aRef != aRefs.cend(); aRef++) {
+ if (!aRef->get() || !(*aRef)->owner().get())
+ continue;
+ // concealed attribute only
+ FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
+ if (alreadyProcessed.find(aRefFeat) != alreadyProcessed.end()) // optimization
+ continue;
+ alreadyProcessed.insert(aRefFeat);
+ if (ModelAPI_Session::get()->validators()->isConcealed(aRefFeat->getKind(), (*aRef)->id()))
+ {
+ // for extrusion cut in python script the nested sketch reference may be concealed before
+ // it is nested, so, check this composite feature is valid
+ static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
+ // need to be validated to update the "Apply" state if not previewed
+ if (aFactory->validate(aRefFeat)) {
+ if (theStop.get()) {
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(theStop->document());
+ if (!aDoc->isLaterByDep(theStop, aRefFeat)) // skip feature later than stop
+ continue;
+ }
+ theConcealers.push_back(aRefFeat);
+ }
+ }
+ }
+ }
+ }
+}
+
bool Model_AttributeSelection::searchNewContext(std::shared_ptr<Model_Document> theDoc,
const TopoDS_Shape theContShape, ResultPtr theContext, TopoDS_Shape theValShape,
TDF_Label theAccessLabel,
if (aResults.empty()) {
// check the context become concealed by operation which is earlier than this selection
- std::list<ResultPtr> allRes;
- ResultPtr aRoot = ModelAPI_Tools::bodyOwner(theContext, true);
- if (!aRoot.get())
- aRoot = theContext;
- ResultBodyPtr aRootBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aRoot);
- if (aRootBody.get()) {
- ModelAPI_Tools::allSubs(aRootBody, allRes);
- allRes.push_back(aRootBody);
- } else
- allRes.push_back(aRoot);
-
FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
- for (std::list<ResultPtr>::iterator aSub = allRes.begin(); aSub != allRes.end(); aSub++) {
- ResultPtr aResCont = *aSub;
- const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
- std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
- for (; aRef != aRefs.end(); aRef++) {
- if (!aRef->get() || !(*aRef)->owner().get())
+ FeaturePtr aContextOwner = theDoc->feature(theContext);
+ std::list<FeaturePtr> aConcealers;
+ concealedFeature(aContextOwner, aThisFeature, aConcealers);
+ std::list<FeaturePtr>::iterator aConcealer = aConcealers.begin();
+ for(; aConcealer != aConcealers.end(); aConcealer++) {
+ std::list<ResultPtr> aRefResults;
+ ModelAPI_Tools::allResults(*aConcealer, aRefResults);
+ std::list<ResultPtr>::iterator aRefIter = aRefResults.begin();
+ for(; aRefIter != aRefResults.end(); aRefIter++) {
+ ResultBodyPtr aRefBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRefIter);
+ if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs
continue;
- // concealed attribute only
- FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
- if (aRefFeat == aThisFeature)
- continue;
- if (!ModelAPI_Session::get()->validators()->isConcealed(
- aRefFeat->getKind(), (*aRef)->id()))
+ GeomShapePtr aRefShape = aRefBody->shape();
+ if (!aRefShape.get() || aRefShape->isNull())
continue;
- if (theDoc->isLaterByDep(aThisFeature, aRefFeat)) {
- // for extrusion cut in python script the nested sketch reference may be concealed before
- // it is nested, so, check this composite feature is valid
- static ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
- // need to be validated to update the "Apply" state if not previewed
- if (aFactory->validate(aRefFeat)) {
- // there could be a reference to unmodified object, check result contain same shape
- std::list<ResultPtr> aRefResults;
- ModelAPI_Tools::allResults(aRefFeat, aRefResults);
- std::list<ResultPtr>::iterator aRefIter = aRefResults.begin();
- for(; aRefIter != aRefResults.end(); aRefIter++) {
- ResultBodyPtr aRefBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aRefIter);
- if (!aRefBody.get() || aRefBody->numberOfSubs() != 0) // iterate only leafs
- continue;
- GeomShapePtr aRefShape = aRefBody->shape();
- if (!aRefShape.get() || aRefShape->isNull())
- continue;
- if (aRefShape->impl<TopoDS_Shape>().IsSame(theContShape)) {
- // add the new context result with the same shape
- aResults.insert(aRefBody);
- }
- }
- if (aResults.empty())
- return true; // feature conceals result, return true, so the context will be removed
- }
+ if (aRefShape->impl<TopoDS_Shape>().IsSame(theContShape)) {
+ // add the new context result with the same shape
+ aResults.insert(aRefBody);
}
}
+ if (aResults.empty())
+ return true; // feature conceals result, return true, so the context will be removed
}
if (aResults.empty())
return false; // no modifications found, must stay the same
void Model_AttributeSelection::updateInHistory(bool& theRemove)
{
+ static std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+
ResultPtr aContext = std::dynamic_pointer_cast<ModelAPI_Result>(myRef.value());
- // only bodies and parts may be modified later in the history, don't do anything otherwise
if (!aContext.get() || (aContext->groupName() != ModelAPI_ResultBody::group() &&
- aContext->groupName() != ModelAPI_ResultPart::group()))
- return;
+ aContext->groupName() != ModelAPI_ResultPart::group())) {
+ // but check the case the whole results are allowed: whole features may be selected
+ if (myParent && myParent->isWholeResultAllowed()) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(myRef.value());
+ if (aFeature.get()) {
+ FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ std::list<FeaturePtr> aConcealers;
+ concealedFeature(aFeature, aThisFeature, aConcealers);
+ if (aConcealers.empty())
+ return;
+ bool aChanged = false;
+ std::list<FeaturePtr>::iterator aConcealer = aConcealers.begin();
+ for(; aConcealer != aConcealers.end(); aConcealer++)
+ if (!myParent->isInList(*aConcealer, anEmptyShape)) {// avoid addition of duplicates
+ setValue(*aConcealer, anEmptyShape);
+ aChanged = true;
+ }
+ if (aConcealer == aConcealers.end()) {
+ if (!aChanged) // remove this
+ theRemove = true;
+ } else { // append new
+ for(aConcealer++; aConcealer != aConcealers.end(); aConcealer++)
+ if (!myParent->isInList(*aConcealer, anEmptyShape)) // avoid addition of duplicates
+ myParent->append(*aConcealer, anEmptyShape);
+ }
+ if (aChanged) // searching for the further modifications
+ updateInHistory(theRemove);
+ }
+ }
+ return;// only bodies and parts may be modified later in the history, skip otherwise
+ }
+
std::shared_ptr<Model_Document> aDoc =
std::dynamic_pointer_cast<Model_Document>(aContext->document());
std::shared_ptr<Model_Data> aContData = std::dynamic_pointer_cast<Model_Data>(aContext->data());
aListShapeType = GeomAPI_Shape::FACE;
}
+ // issue #3031: skip topology if there is more convenient shape type presents in the
+ // same context as a result of this
+ bool isWholeResult = myParent && myParent->isWholeResultAllowed() && !aSubShape.get();
+ GeomAPI_Shape::ShapeType allowedType = GeomAPI_Shape::SHAPE;
+ if (isWholeResult) {
+ std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
+ TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
+ for(; aNewCont != aNewContexts.end(); aNewCont++, aNewValues.Next()) {
+ if (aNewValues.Value().IsNull()) { // only for the whole context
+ GeomAPI_Shape::ShapeType aShapeType = (*aNewCont)->shape()->shapeType();
+ if (allowedType == GeomAPI_Shape::SHAPE) { // just set this one
+ allowedType = aShapeType;
+ } else {
+ GeomAPI_Shape::ShapeType anAllowed = allowedType;
+ if (anAllowed != aShapeType) { // select the best, nearest to the origin
+ GeomAPI_Shape::ShapeType anOldShapeType = aContext->shape()->shapeType();
+ GeomAPI_Shape::ShapeType aDeltaAllowed =
+ (GeomAPI_Shape::ShapeType)(anOldShapeType - anAllowed);
+ if (aDeltaAllowed < 0)
+ aDeltaAllowed = (GeomAPI_Shape::ShapeType)(-aDeltaAllowed);
+ GeomAPI_Shape::ShapeType aDeltaThis =
+ (GeomAPI_Shape::ShapeType)(anOldShapeType - aShapeType);
+ if (aDeltaThis < 0)
+ aDeltaThis = (GeomAPI_Shape::ShapeType)(-aDeltaThis);
+ if (aDeltaThis == aDeltaAllowed) { // equal distance to context, select complicated
+ if (anOldShapeType < anAllowed)
+ allowedType = aShapeType;
+ } else if (aDeltaAllowed > aDeltaThis) { // this wins
+ allowedType = aShapeType;
+ }
+ }
+ }
+ }
+ }
+ }
+
std::list<ResultPtr>::iterator aNewCont = aNewContexts.begin();
TopTools_ListIteratorOfListOfShape aNewValues(aValShapes);
bool aFirst = true; // first is set to this, next are appended to parent
if (aSkippedContext.count(*aNewCont))
continue;
+ if (isWholeResult && aNewValues.Value().IsNull())
+ if (allowedType != GeomAPI_Shape::SHAPE &&
+ (*aNewCont)->shape()->shapeType() != allowedType)
+ continue; // there is better result exists with the better shape type (issue #3031)
+
GeomShapePtr aValueShape;
if (!aNewValues.Value().IsNull()) {
aValueShape = std::make_shared<GeomAPI_Shape>();
aShapeShapeType = (*aNewCont)->shape()->shapeType();
}
if (aListShapeType != GeomAPI_Shape::SHAPE && aListShapeType != aShapeShapeType) {
- continue;
+ // exception is for whole results selected
+ if (!isWholeResult) {
+ continue;
+ }
}
ResultPtr aNewContext = *aNewCont;
if (myParent) {
theRemove = true;
} else {
- ResultPtr anEmptyContext;
- std::shared_ptr<GeomAPI_Shape> anEmptyShape;
+ static ResultPtr anEmptyContext;
setValue(anEmptyContext, anEmptyShape); // nullify the selection
return;
}
const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
const bool theTemporarily = false);
- /// Same as SetValue, but it takes an edge (on circular or elliptical curve)
+ /// Same as SetValue, but it takes an edge (on circular or elliptic curve)
/// and stores the vertex of the central point (for ellipse the first or the second focus point)
MODEL_EXPORT virtual void setValueCenter(
const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
/// Returns null label otherwise.
TDF_Label baseDocumentLab();
+ /// Returns features that conceals theFeature and located in history before theStop
+ void concealedFeature(
+ const FeaturePtr theFeature, const FeaturePtr theStop, std::list<FeaturePtr>& theConcealers);
+
friend class Model_Data;
friend class Model_AttributeSelectionList;
};
const std::shared_ptr<GeomAPI_Shape>& theSubShape,
const bool theTemporarily)
{
- ResultPtr aResCont = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
if (myIsCashed) { // the cashing is active
- if (aResCont.get()) {
- std::map<ResultPtr, std::list<std::shared_ptr<GeomAPI_Shape> > >::iterator aContext =
- myCash.find(aResCont);
+ if (theContext.get()) {
+ std::map<ObjectPtr, std::list<std::shared_ptr<GeomAPI_Shape> > >::iterator aContext =
+ myCash.find(theContext);
if (aContext != myCash.end()) {
// iterate shapes because "isSame" method must be called for each shape
std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aShapes = aContext->second.begin();
for(; aShapes != aContext->second.end(); aShapes++) {
if (!theSubShape.get()) {
- if (!aShapes->get() || (*aShapes)->isSame(aContext->first->shape()))
+ if (!aShapes->get())
+ return true;
+ ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aContext->first);
+ if (aRes.get() && (*aShapes)->isSame(aRes->shape()))
return true;
} else {
// we need to call here isSame instead of isEqual to do not check shapes orientation
}
}
// no-cash method
+ bool isFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theContext).get() != NULL;
+ ResultPtr aRes;
+ if (!isFeature)
+ aRes = std::dynamic_pointer_cast<ModelAPI_Result>(theContext);
for(int anIndex = size() - 1; anIndex >= 0; anIndex--) {
AttributeSelectionPtr anAttr = value(anIndex);
if (anAttr.get()) {
- if (anAttr->context() == theContext) { // contexts are equal, so, check that values are also
+ if (isFeature && anAttr->contextFeature() == theContext)
+ return true; // for the feature value should not be compared
+ if (!isFeature && anAttr->context() == theContext) {
+ // contexts are equal, so, check that values are also
std::shared_ptr<GeomAPI_Shape> aValue = anAttr->value();
if (!theSubShape.get()) {
- if (!aValue.get() || (aResCont.get() && aValue->isSame(aResCont->shape()))) {// both null
+ if (!aValue.get() || (aRes.get() && aValue->isSame(aRes->shape())))
return true;
- }
} else {
// we need to call here isSame instead of isEqual to do not check shapes orientation
if (isIn(aValue, theSubShape)) // shapes are equal
}
Model_AttributeSelectionList::Model_AttributeSelectionList(TDF_Label& theLabel)
-: myLab(theLabel)
+: ModelAPI_AttributeSelectionList(), myLab(theLabel)
{
reinit();
}
Handle(TDataStd_Comment) mySelectionType;
std::shared_ptr<Model_AttributeSelection> myTmpAttr; ///< temporary attribute (the last one)
/// the cashed shapes to optimize isInList method: from context to set of shapes in this context
- std::map<ResultPtr, std::list<std::shared_ptr<GeomAPI_Shape> > > myCash;
+ std::map<ObjectPtr, std::list<std::shared_ptr<GeomAPI_Shape> > > myCash;
bool myIsCashed; ///< true if cashing is performed
public:
/// Adds the new reference to the end of the list
#include <ModelAPI_Data.h>
#include <ModelAPI_Object.h>
+#include <TDataStd_UAttribute.hxx>
#include <Standard_TypeDef.hxx>
#include <TCollection_AsciiString.hxx>
#include <TCollection_ExtendedString.hxx>
#include <string>
+// on myLabel if the Unicode string was stored
+static const Standard_GUID kUVALUE_IDENTIFIER("04cac509-b2fc-4887-b442-d2a86f2fd7bd");
+
void Model_AttributeString::setValue(const std::string& theValue)
{
TCollection_ExtendedString aValue(theValue.c_str());
if (myString.IsNull())
myString = TDataStd_Name::Set(myLab, TCollection_ExtendedString());
myString->Set(aValue);
+ myLab.ForgetAttribute(kUVALUE_IDENTIFIER);
owner()->data()->sendAttributeUpdated(this);
}
}
if (myString.IsNull())
myString = TDataStd_Name::Set(myLab, TCollection_ExtendedString());
myString->Set(aValue);
+ TDataStd_UAttribute::Set(myLab, kUVALUE_IDENTIFIER);
owner()->data()->sendAttributeUpdated(this);
}
}
return ""; // not initialized
return TCollection_AsciiString(myString->Get()).ToCString();
}
+
char16_t* Model_AttributeString::valueU()
{
if (myString.IsNull()) { // not initialized
return (char16_t*)(myString->Get().ToExtString());
}
+bool Model_AttributeString::isUValue() const {
+ return !myLab.IsNull() && myLab.IsAttribute(kUVALUE_IDENTIFIER);
+}
+
Model_AttributeString::Model_AttributeString(TDF_Label& theLabel)
{
myLab = theLabel;
MODEL_EXPORT virtual std::string value();
/// Returns a pointer to Unicode string
MODEL_EXPORT virtual char16_t* valueU();
+ /// Returns true if Unicode string was stored
+ MODEL_EXPORT virtual bool isUValue() const;
protected:
/// Initializes attributes
// 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);
aCurrent = aSub;
}
}
- // #2861: if the parameter is added, add it after parameters existing in the list
- if (aCurrent.get() &&
- (aFeature->getKind() == "Parameter" || aFeature->getKind() == "ParametersMgr")) {
- int anIndex = kUNDEFINED_FEATURE_INDEX;
- for(FeaturePtr aNextFeat = myObjs->nextFeature(aCurrent, anIndex);
- aNextFeat.get() && aNextFeat->getKind() == "Parameter";
- aNextFeat = myObjs->nextFeature(aCurrent, anIndex))
- aCurrent = aNextFeat;
- }
+ }
+ // #2861,3029: if the parameter is added, add it after parameters existing in the list
+ if (aCurrent.get() &&
+ (aFeature->getKind() == "Parameter" || aFeature->getKind() == "ParametersMgr")) {
+ int anIndex = kUNDEFINED_FEATURE_INDEX;
+ for(FeaturePtr aNextFeat = myObjs->nextFeature(aCurrent, anIndex);
+ aNextFeat.get() && aNextFeat->getKind() == "Parameter";
+ aNextFeat = myObjs->nextFeature(aCurrent, anIndex))
+ aCurrent = aNextFeat;
}
aDocToAdd->myObjs->addFeature(aFeature, aCurrent);
if (!aFeature->isAction()) { // do not add action to the data model
myNotObligatory.find(theFeature->getKind());
if (aFeatureFind == myNotObligatory.end() || // and it is obligatory for filling
aFeatureFind->second.find(*it) == aFeatureFind->second.end()) {
- // TODO(spo): exceptional case for translation
- theError = "Attribute \"" + anAttr->id() + "\" is not initialized.";
-// theError.arg(anAttr->id());
+ theError = "Attribute \"%1\" is not initialized.";
+ theError.addParameter(anAttr->id());
+ theError.setContext(theFeature->getKind() + ":" + anAttr->id());
return false;
}
}
#include <ModelAPI_AttributeSelectionList.h>
#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <Config_PropManager.h>
if (!aResult && myOwnerData) {
AttributeSelectionListPtr aList = myOwnerData->selectionList("group_list");
if (aList) {
+ GeomAPI_DataMapOfShapeShape aShapesMap; // to avoid shapes duplication
std::list<std::shared_ptr<GeomAPI_Shape> > aSubs;
for(int a = aList->size() - 1; a >= 0; a--) {
std::shared_ptr<GeomAPI_Shape> aSelection = aList->value(a)->value();
- if (aSelection && !aSelection->isNull()) {
- aSubs.push_back(aSelection);
+ if (aList->isWholeResultAllowed()) { // whole result selection, explode to sub-shapes
+ if (!aSelection.get() || aSelection->isNull()) {
+ ResultPtr aContext = aList->value(a)->context();
+ if (aContext)
+ aSelection = aContext->shape();
+ }
+ if (aSelection && !aSelection->isNull()) {
+ GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(aList->selectionType());
+ if (aType == aSelection->shapeType()) {
+ if (aShapesMap.bind(aSelection, aSelection))
+ aSubs.push_back(aSelection);
+ } else {
+ for(GeomAPI_ShapeExplorer anExp(aSelection, aType); anExp.more(); anExp.next()) {
+ if (aShapesMap.bind(anExp.current(), anExp.current()))
+ aSubs.push_back(anExp.current());
+ }
+ }
+ }
+ } else { // take selection as it is
+ if (aSelection && !aSelection->isNull()) {
+ if (aShapesMap.bind(aSelection, aSelection))
+ aSubs.push_back(aSelection);
+ }
}
}
if (!aSubs.empty()) {
TopoDS_Shape aBodyShape = *(aBody->shape()->implPtr<TopoDS_Shape>());
// check is body contain the selected sub-shape
for(TopExp_Explorer anExp(aBodyShape, aShape.ShapeType()); anExp.More(); anExp.Next()) {
- if (aShape.IsEqual(anExp.Current())) {
+ if (aShape.IsSame(anExp.Current())) {
aContext = aBody;
break;
}
}
// searching for the next not used reason
aProcessedReasons.insert(aReason);
- aReasons.erase(aReason);
+ // check theFeature is still in the list of modified, because it may be removed sometimes
+ // while updating SketchPlugin_Ellipse
+ if (myModified.find(theFeature) != myModified.end())
+ aReasons.erase(aReason);
+ else
+ break;
}
// restore the modified reasons: they will be used in the update of arguments
if (allSubsUsed) { // restore theFeature in this set
TestSaveOpen1.py
TestSaveOpen2.py
TestSelectionInitialization.py
+ TestSelectionCircleCenter.py
+ TestSelectionInPart.py
Test2828.py
TestSelectionRestore.py
Test2491.py
Test2873.py
Test2901.py
Test2903.py
+ Test3020.py
)
class ModelAPI_AttributeSelection : public ModelAPI_Attribute
{
public:
- /// Type of the center of the circular of elliptical edge
+ /// Type of the center of the circular of elliptic edge
enum CenterType {
NOT_CENTER, ///< this is not a center
CIRCLE_CENTER, ///< center of the circle
const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape,
const bool theTemporarily = false) = 0;
- /// Same as SetValue, but it takes an edge (on circular or elliptical curve)
+ /// Same as SetValue, but it takes an edge (on circular or elliptic curve)
/// and stores the vertex of the central point (for ellipse the first or the second focus point)
virtual void setValueCenter(
const ObjectPtr& theContext, const std::shared_ptr<GeomAPI_Edge>& theEdge,
ModelAPI_AttributeSelectionList::~ModelAPI_AttributeSelectionList()
{
}
-
-MODELAPI_EXPORT ModelAPI_AttributeSelectionList::ModelAPI_AttributeSelectionList()
-{
-}
class ModelAPI_AttributeSelectionList : public ModelAPI_Attribute
{
+ /// Flag that indicates that the whole result selection is allowed while the selection type
+ /// may be sub-objects, so, it is the same as all sub-shapes are selected (#3005). It is "false"
+ /// by default.
+ bool myIsWholeResultAllowed;
public:
/// Adds the new reference to the end of the list
/// \param theContext object where the sub-shape was selected
/// Sets a selection filters feature if it is defined for this selection list
MODELAPI_EXPORT virtual void setFilters(FiltersFeaturePtr theFeature) = 0;
+ /// Returns true if the whole result selection corresponds to selection of all sub-shapes.
+ MODELAPI_EXPORT virtual const bool isWholeResultAllowed() const {
+ return myIsWholeResultAllowed;
+ }
+
+ /// Sets whether the whole result selection corresponds to selection of all sub-shapes.
+ MODELAPI_EXPORT virtual void setWholeResultAllowed(const bool theFlag) {
+ myIsWholeResultAllowed = theFlag;
+ }
+
protected:
- /// Objects are created for features automatically
- MODELAPI_EXPORT ModelAPI_AttributeSelectionList();
+ /// Default constructor
+ MODELAPI_EXPORT ModelAPI_AttributeSelectionList() : ModelAPI_Attribute()
+ {myIsWholeResultAllowed = false;}
};
MODELAPI_EXPORT virtual std::string value() = 0;
/// Returns a pointer to Unicode string
MODELAPI_EXPORT virtual char16_t* valueU() = 0;
+ MODELAPI_EXPORT virtual bool isUValue() const = 0;
/// Returns the type of this class of attributes
MODELAPI_EXPORT static std::string typeId()
--- /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
+#
+
+from salome.shaper import model
+from ModelAPI 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"))
+SketchCircle_1 = Sketch_1.addCircle(25, 20, 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2r")], model.selection(), 20, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face"))
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]__cc"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_2 = Sketch_2.addCircle(25, 20, 5)
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchPoint_1.result(), SketchCircle_2.center())
+model.end()
+# check the sketch_2 projection and the whole sketch is valid after selection of the circle center from another part
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(SketchProjection_1.feature()))
+assert(aFactory.validate(Sketch_2.feature()))
+
+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
+#
+
+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"))
+SketchLine_1 = Sketch_1.addLine(15, 10, -10, 10)
+SketchLine_2 = Sketch_1.addLine(-10, 10, -10, -10)
+SketchLine_3 = Sketch_1.addLine(-10, -10, 20, -10)
+SketchLine_4 = Sketch_1.addLine(20, -10, 20, 5)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_1.setName("SketchConstraintCoincidence_2")
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_2.setName("SketchConstraintCoincidence_3")
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintCoincidence_3.setName("SketchConstraintCoincidence_4")
+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())
+SketchArc_1 = Sketch_1.addArc(15, 5, 20, 5, 15, 10, False)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchArc_1.startPoint(), SketchLine_4.endPoint())
+SketchConstraintCoincidence_4.setName("SketchConstraintCoincidence_5")
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_1.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_5.setName("SketchConstraintCoincidence_6")
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_1.result())
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_1.results()[1], SketchLine_4.result())
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_2.result(), 20)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_3.result(), 30)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 5)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchProjection_1.setName("SketchProjection_3")
+SketchProjection_1.result().setName("SketchProjection_3")
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchPoint_1.setName("SketchPoint_3")
+SketchPoint_1.result().setName("SketchPoint_3")
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_2.startPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_2.endPoint(), SketchAPI_Point(SketchPoint_1).coordinates(), 10)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f-SketchArc_1_2f")], model.selection(), 10, 0)
+Fillet_1 = model.addFillet(Part_1_doc, [model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_2][Extrusion_1_1/Generated_Face&Sketch_1/SketchLine_3]")], 10)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Fillet_1_1/MF:Fillet&Extrusion_1_1/To_Face"))
+SketchLine_5 = Sketch_2.addLine(15, 5, 0, 0)
+SketchProjection_2 = Sketch_2.addProjection(model.selection("VERTEX", "[Fillet_1_1/MF:Fillet&Extrusion_1_1/To_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchArc_1_2]__cc"), False)
+SketchProjection_2.setName("SketchProjection_1")
+SketchProjection_2.result().setName("SketchProjection_1")
+SketchPoint_2 = SketchProjection_2.createdFeature()
+SketchPoint_2.setName("SketchPoint_1")
+SketchPoint_2.result().setName("SketchPoint_1")
+SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.startPoint(), SketchPoint_2.result())
+SketchConstraintCoincidence_6.setName("SketchConstraintCoincidence_7")
+SketchProjection_3 = Sketch_2.addProjection(model.selection("VERTEX", "[Fillet_1_1/GF:Fillet&Fillet_1_1/FilletSelected][Fillet_1_1/MF:Fillet&Extrusion_1_1/To_Face]__cc"), False)
+SketchProjection_3.setName("SketchProjection_2")
+SketchProjection_3.result().setName("SketchProjection_2")
+SketchPoint_3 = SketchProjection_3.createdFeature()
+SketchPoint_3.setName("SketchPoint_2")
+SketchPoint_3.result().setName("SketchPoint_2")
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchPoint_3.result())
+SketchConstraintCoincidence_7.setName("SketchConstraintCoincidence_8")
+model.end()
+# check that the second line-point was created on the point, not arc
+assert(len(SketchPoint_3.feature().results()) == 1)
+assert(SketchPoint_3.feature().firstResult().shape().isVertex())
--- /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
+#
+
+from SketchAPI import *
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+model.addParameter(partSet, "ShaftSize", "16")
+model.addParameter(partSet, "ShaftChamfer", "0.2")
+model.addParameter(partSet, "ToolHeight", "5")
+model.addParameter(partSet, "ToolDraftAngle", "11")
+model.addParameter(partSet, "ScrewDiam", "3.5")
+model.addParameter(partSet, "ThreadDiam", "ScrewDiam+1")
+model.addParameter(partSet, "ScrewHeight", "12")
+model.addParameter(partSet, "ToolEdgeSize", "9")
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("YOZ"))
+SketchLine_1 = Sketch_1.addLine(7.8, 0, -7.8, 0)
+SketchLine_2 = Sketch_1.addLine(-8, 0.2, -8, 15.8)
+SketchLine_3 = Sketch_1.addLine(-7.8, 16, 7.8, 16)
+SketchLine_4 = Sketch_1.addLine(8, 15.8, 8, 0.2)
+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())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintMiddle_1 = Sketch_1.setMiddlePoint(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_1.result())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_1.result())
+SketchLine_5 = Sketch_1.addLine(-8, 0.2, -7.8, 0)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_5.endPoint())
+SketchLine_6 = Sketch_1.addLine(7.8, 0, 8, 0.2)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_6.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_6.endPoint())
+SketchLine_7 = Sketch_1.addLine(-8, 15.8, -7.8, 16)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_7.startPoint())
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.startPoint(), SketchLine_7.endPoint())
+SketchLine_8 = Sketch_1.addLine(7.8, 16, 8, 15.8)
+SketchConstraintCoincidence_7 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_8.startPoint())
+SketchConstraintCoincidence_8 = Sketch_1.setCoincident(SketchLine_4.startPoint(), SketchLine_8.endPoint())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_3.result())
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_4.result())
+SketchConstraintEqual_4 = Sketch_1.setEqual(SketchLine_5.result(), SketchLine_6.result())
+SketchConstraintEqual_5 = Sketch_1.setEqual(SketchLine_6.result(), SketchLine_7.result())
+SketchConstraintEqual_6 = Sketch_1.setEqual(SketchLine_7.result(), SketchLine_8.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_5.startPoint(), SketchLine_4.result(), "ShaftSize", True)
+SketchConstraintDistance_2 = Sketch_1.setDistance(SketchLine_1.endPoint(), SketchLine_3.result(), "ShaftSize", True)
+SketchConstraintDistanceHorizontal_1 = Sketch_1.setHorizontalDistance(SketchLine_5.startPoint(), SketchLine_1.endPoint(), "ShaftChamfer")
+SketchConstraintDistanceVertical_1 = Sketch_1.setVerticalDistance(SketchLine_1.endPoint(), SketchLine_5.startPoint(), "ShaftChamfer")
+model.do()
+Part_1 = model.addPart(partSet)
+Part_1.setName("TurnShaft")
+Part_1.result().setName("TurnShaft")
+Part_1.result().setColor(75, 75, 75)
+Part_1_doc = Part_1.document()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "PartSet/Sketch_1/Face-SketchLine_6f-SketchLine_4r-SketchLine_8r-SketchLine_3r-SketchLine_7r-SketchLine_2r-SketchLine_5f-SketchLine_1r")], model.selection(), 100, 0)
+ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection("FACE", "Extrusion_1_1/Generated_Face&PartSet/Sketch_1/SketchLine_4"), 0, model.selection(), 0, [model.selection("SOLID", "Extrusion_1_1")])
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&PartSet/Sketch_1/SketchLine_2"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/Sketch_1/SketchLine_7"), True)
+SketchLine_9 = SketchProjection_2.createdFeature()
+SketchLine_10 = Sketch_2.addLine(0, 15.8, 0.2, 16)
+SketchConstraintCoincidence_9 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_9).startPoint(), SketchLine_10.startPoint())
+SketchLine_11 = Sketch_2.addLine(0.2, 16, 0, 16)
+SketchConstraintCoincidence_10 = Sketch_2.setCoincident(SketchLine_10.endPoint(), SketchLine_11.startPoint())
+SketchConstraintCoincidence_11 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_9).endPoint(), SketchLine_11.endPoint())
+SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_11.result())
+SketchConstraintEqual_7 = Sketch_2.setEqual(SketchLine_9.result(), SketchLine_11.result())
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/Sketch_1/SketchLine_5"), True)
+SketchLine_12 = SketchProjection_3.createdFeature()
+SketchLine_13 = Sketch_2.addLine(0, 0.2, 0.2, 0)
+SketchConstraintCoincidence_12 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_12).startPoint(), SketchLine_13.startPoint())
+SketchLine_14 = Sketch_2.addLine(0.2, 0, 0, 0)
+SketchConstraintCoincidence_13 = Sketch_2.setCoincident(SketchLine_13.endPoint(), SketchLine_14.startPoint())
+SketchConstraintCoincidence_14 = Sketch_2.setCoincident(SketchAPI_Line(SketchLine_12).endPoint(), SketchLine_14.endPoint())
+SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_14.result())
+SketchConstraintEqual_8 = Sketch_2.setEqual(SketchLine_12.result(), SketchLine_14.result())
+ExtrusionCut_1.setNestedSketch(Sketch_2)
+ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&PartSet/Sketch_1/SketchLine_1"), 0, model.selection(), 0, [model.selection("SOLID", "ExtrusionCut_1_1")])
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&PartSet/Sketch_1/SketchLine_3"))
+SketchProjection_4 = Sketch_3.addProjection(model.selection("EDGE", "[ExtrusionCut_1_1/Modified_Face&PartSet/Sketch_1/SketchLine_3][ExtrusionCut_1_1/Generated_Face&Sketch_1/SketchLine_2]"), False)
+SketchLine_15 = SketchProjection_4.createdFeature()
+SketchProjection_5 = Sketch_3.addProjection(model.selection("VERTEX", "PartSet/Sketch_1/SketchLine_2_EndVertex"), False)
+SketchPoint_2 = SketchProjection_5.createdFeature()
+SketchLine_16 = Sketch_3.addLine(0, -8, 0.2, -8)
+SketchConstraintCoincidence_15 = Sketch_3.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_16.startPoint())
+SketchLine_17 = Sketch_3.addLine(0.2, -8, 0, -7.8)
+SketchConstraintCoincidence_16 = Sketch_3.setCoincident(SketchLine_16.endPoint(), SketchLine_17.startPoint())
+SketchLine_18 = Sketch_3.addLine(0, -7.8, 0, -8)
+SketchConstraintCoincidence_17 = Sketch_3.setCoincident(SketchLine_17.endPoint(), SketchLine_18.startPoint())
+SketchConstraintCoincidence_18 = Sketch_3.setCoincident(SketchAPI_Point(SketchPoint_2).coordinates(), SketchLine_18.endPoint())
+SketchConstraintHorizontal_5 = Sketch_3.setHorizontal(SketchLine_16.result())
+SketchConstraintVertical_3 = Sketch_3.setVertical(SketchLine_18.result())
+SketchConstraintEqual_9 = Sketch_3.setEqual(SketchLine_16.result(), SketchLine_18.result())
+SketchConstraintCoincidence_19 = Sketch_3.setCoincident(SketchLine_16.endPoint(), SketchLine_15.result())
+SketchProjection_6 = Sketch_3.addProjection(model.selection("VERTEX", "PartSet/Sketch_1/SketchLine_8_EndVertex"), False)
+SketchPoint_3 = SketchProjection_6.createdFeature()
+SketchLine_19 = Sketch_3.addLine(0, 8, 0, 7.8)
+SketchConstraintCoincidence_20 = Sketch_3.setCoincident(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_19.startPoint())
+SketchLine_20 = Sketch_3.addLine(0, 7.8, 0.2, 8)
+SketchConstraintCoincidence_21 = Sketch_3.setCoincident(SketchLine_19.endPoint(), SketchLine_20.startPoint())
+SketchLine_21 = Sketch_3.addLine(0.2, 8, 0, 8)
+SketchConstraintCoincidence_22 = Sketch_3.setCoincident(SketchLine_20.endPoint(), SketchLine_21.startPoint())
+SketchConstraintCoincidence_23 = Sketch_3.setCoincident(SketchAPI_Point(SketchPoint_3).coordinates(), SketchLine_21.endPoint())
+SketchConstraintVertical_4 = Sketch_3.setVertical(SketchLine_19.result())
+SketchConstraintHorizontal_6 = Sketch_3.setHorizontal(SketchLine_21.result())
+SketchConstraintEqual_10 = Sketch_3.setEqual(SketchLine_19.result(), SketchLine_21.result())
+SketchConstraintCoincidence_24 = Sketch_3.setCoincident(SketchLine_20.endPoint(), SketchLine_15.result())
+ExtrusionCut_2.setNestedSketch(Sketch_3)
+ExtrusionCut_3 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 3, [model.selection("SOLID", "ExtrusionCut_2_1")])
+Sketch_4 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&PartSet/Sketch_1/SketchLine_3"))
+SketchCircle_1 = Sketch_4.addCircle(10, 0, 5)
+SketchProjection_7 = Sketch_4.addProjection(model.selection("EDGE", "[ExtrusionCut_2_1/Modified_Face&Extrusion_1_1/From_Face][ExtrusionCut_2_1/Modified_Face&Sketch_1/SketchLine_2]"), False)
+SketchLine_22 = SketchProjection_7.createdFeature()
+SketchLine_23 = Sketch_4.addLine(10, 0, 0, 0)
+SketchLine_23.setAuxiliary(True)
+SketchConstraintCoincidence_25 = Sketch_4.setCoincident(SketchCircle_1.center(), SketchLine_23.startPoint())
+SketchConstraintCoincidence_26 = Sketch_4.setCoincident(SketchLine_23.endPoint(), SketchLine_22.result())
+SketchConstraintMiddle_2 = Sketch_4.setMiddlePoint(SketchLine_23.endPoint(), SketchLine_22.result())
+SketchConstraintPerpendicular_1 = Sketch_4.setPerpendicular(SketchLine_23.result(), SketchLine_22.result())
+SketchConstraintRadius_1 = Sketch_4.setRadius(SketchCircle_1.results()[1], 5)
+SketchConstraintLength_1 = Sketch_4.setLength(SketchLine_23.result(), 10)
+ExtrusionCut_3.setNestedSketch(Sketch_4)
+model.do()
+Part_2 = model.addPart(partSet)
+Part_2.setName("Stamp")
+Part_2.result().setName("Stamp")
+Part_2_doc = Part_2.document()
+Sketch_5 = model.addSketch(Part_2_doc, model.defaultPlane("XOZ"))
+SketchProjection_8 = Sketch_5.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_4 = SketchProjection_8.createdFeature()
+SketchCircle_2 = Sketch_5.addCircle(0, 0, 5)
+SketchConstraintCoincidence_27 = Sketch_5.setCoincident(SketchPoint_4.result(), SketchCircle_2.center())
+SketchConstraintRadius_2 = Sketch_5.setRadius(SketchCircle_2.results()[1], 5)
+model.do()
+Extrusion_2 = model.addExtrusion(Part_2_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 10, 0)
+model.do()
+Placement_1 = model.addPlacement(partSet, [model.selection("COMPOUND", "Stamp/")], model.selection("FACE", "Stamp/Extrusion_1_1/To_Face"), model.selection("FACE", "TurnShaft/ExtrusionCut_3_1/From_Face"), False, True)
+model.end()
+
+# check that names of selection are exported and imported correctly
+assert(model.checkPythonDump())
aShell = GeomAPI_ShapeExplorer(aBoxResult.shape(), GeomAPI_Shape.SHELL)
aGroup = Part_1_doc.addFeature("Group")
aGroup.selectionList("group_list").append(aBoxResult, aShell.current())
+aGroup.selectionList("group_list").setSelectionType("SHELL") # to compute the shape for the whole result selection correctly
model.end()
# check that the resulting group is correct
{
bool isInside = false;
if (theBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
- std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
- if (anEdge->isLine()) {
- std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
- theProjectedPoint = aLine->project(thePoint);
- }
- else if (anEdge->isCircle() || anEdge->isArc()) {
- std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
- theProjectedPoint = aCircle->project(thePoint);
- }
+ GeomCurvePtr aCurve(new GeomAPI_Curve(theBaseShape->edge()));
+ theProjectedPoint = aCurve->project(thePoint);
if (theProjectedPoint.get()) {
std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(theProjectedPoint->x(),
theProjectedPoint->y(), theProjectedPoint->z()));
bool isInside = isPointOnEdge(theBaseShape, thePoint, theProjectedPoint);
if (isInside) {
std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
- if (!anEdge->isCircle()) {
+ if (!anEdge->isClosed()) {
// check the point is not on the boundary
GeomVertexPtr aVertex(new GeomAPI_Vertex(theProjectedPoint->x(),
theProjectedPoint->y(), theProjectedPoint->z()));
return aFoundSubs;
}
- // Find circular/elliptical edge, which center/focus coincide with the given point
+ // Find circular/elliptic edge, which center/focus coincide with the given point
static GeomShapePtr findEdgeByCenter(const GeomShapePtr& theBaseShape,
const GeomPointPtr& theCenter,
const double theTolerance,
std::shared_ptr<ModelAPI_Attribute> * temp_attribute;
std::shared_ptr<ModelAPI_Object> * temp_object;
std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
+ ModelHighAPI_Selection* temp_selection;
int newmem = 0;
+ if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (!temp_selection) {
+ PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
+ return NULL;
+ }
+ temp = ModelHighAPI_RefAttr(std::shared_ptr<ModelAPI_Object>(temp_selection->resultSubShapePair().first));
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ delete temp_selection;
+ }
+ $1 = &temp;
+ } else
if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_attribute, $descriptor(std::shared_ptr<ModelAPI_Attribute> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
if (!temp_attribute) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
+ PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
return NULL;
}
temp = ModelHighAPI_RefAttr(*temp_attribute);
} else
if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_object, $descriptor(std::shared_ptr<ModelAPI_Object> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
if (!temp_object) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
+ PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
return NULL;
}
temp = ModelHighAPI_RefAttr(*temp_object);
} else
if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_interface, $descriptor(std::shared_ptr<ModelHighAPI_Interface> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
if (!temp_interface) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
+ PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
return NULL;
}
temp = ModelHighAPI_RefAttr(*temp_interface);
} else
if ((SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, SWIG_POINTER_EXCEPTION)) == 0) {
} else {
- PyErr_SetString(PyExc_ValueError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
+ PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
return NULL;
}
}
$result = SWIG_NewPointerObj( (void*) ptr, $1_descriptor, 1 );
}
+%typemap(out) const ModelHighAPI_RefAttr & {
+ $1_basetype * ptr = new $1_basetype(*$1);
+ $result = SWIG_NewPointerObj( (void*) ptr, $1_descriptor, 1 );
+}
+
// std::list -> []
%template(SelectionList) std::list<ModelHighAPI_Selection>;
%template(SelectionListList) std::list<std::list<ModelHighAPI_Selection> >;
// Check the attribute belongs to copied (in multi-translation or multi-rotation) feature.
// In this case we need to cast explicitly feature to appropriate type.
AttributeBooleanPtr isCopy = anOwner->boolean("Copy");
- if (isCopy.get() && isCopy->value()) {
+ AttributeReferencePtr hasParent = anOwner->reference("ParentFeature");
+ if ((isCopy.get() && isCopy->value()) || (hasParent && hasParent->value())) {
aWrapperPrefix = featureWrapper(anOwner) + "(";
aWrapperSuffix = ")";
importModule("SketchAPI");
std::list<std::string> aResList; // list of resulting strings
for(std::list<ObjectPtr>::iterator aL = aList.begin(); aL != aList.end(); aL++) {
if (aL->get()) {
+ if (isSketchFeatures) {
+ // do not control construction features of an ellipse and other
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*aL);
+ if (aFeature->getKind() == "SketchConstraintCoincidenceInternal")
+ continue; // skip internal constraints
+ }
aResList.push_back((*aL)->data()->name());
} else if (!isSketchFeatures) {
aResList.push_back("__empty__");
END_INIT() \
public:
+//--------------------------------------------------------------------------------------
+#define INTERFACE_13(KIND, \
+ N_0, AN_0, T_0, C_0, \
+ N_1, AN_1, T_1, C_1, \
+ N_2, AN_2, T_2, C_2, \
+ N_3, AN_3, T_3, C_3, \
+ N_4, AN_4, T_4, C_4, \
+ N_5, AN_5, T_5, C_5, \
+ N_6, AN_6, T_6, C_6, \
+ N_7, AN_7, T_7, C_7, \
+ N_8, AN_8, T_8, C_8, \
+ N_9, AN_9, T_9, C_9, \
+ N_10, AN_10, T_10, C_10, \
+ N_11, AN_11, T_11, C_11, \
+ N_12, AN_12, T_12, C_12) \
+ public: \
+ INTERFACE_COMMON(KIND) \
+ DEFINE_ATTRIBUTE(N_0, T_0, C_0) \
+ DEFINE_ATTRIBUTE(N_1, T_1, C_1) \
+ DEFINE_ATTRIBUTE(N_2, T_2, C_2) \
+ DEFINE_ATTRIBUTE(N_3, T_3, C_3) \
+ DEFINE_ATTRIBUTE(N_4, T_4, C_4) \
+ DEFINE_ATTRIBUTE(N_5, T_5, C_5) \
+ DEFINE_ATTRIBUTE(N_6, T_6, C_6) \
+ DEFINE_ATTRIBUTE(N_7, T_7, C_7) \
+ DEFINE_ATTRIBUTE(N_8, T_8, C_8) \
+ DEFINE_ATTRIBUTE(N_9, T_9, C_9) \
+ DEFINE_ATTRIBUTE(N_10, T_10, C_10) \
+ DEFINE_ATTRIBUTE(N_11, T_11, C_11) \
+ DEFINE_ATTRIBUTE(N_12, T_12, C_12) \
+ protected: \
+ START_INIT() \
+ SET_ATTRIBUTE(N_0, T_0, AN_0) \
+ SET_ATTRIBUTE(N_1, T_1, AN_1) \
+ SET_ATTRIBUTE(N_2, T_2, AN_2) \
+ SET_ATTRIBUTE(N_3, T_3, AN_3) \
+ SET_ATTRIBUTE(N_4, T_4, AN_4) \
+ SET_ATTRIBUTE(N_5, T_5, AN_5) \
+ SET_ATTRIBUTE(N_6, T_6, AN_6) \
+ SET_ATTRIBUTE(N_7, T_7, AN_7) \
+ SET_ATTRIBUTE(N_8, T_8, AN_8) \
+ SET_ATTRIBUTE(N_9, T_9, AN_9) \
+ SET_ATTRIBUTE(N_10, T_10, AN_10) \
+ SET_ATTRIBUTE(N_11, T_11, AN_11) \
+ SET_ATTRIBUTE(N_12, T_12, AN_12) \
+ END_INIT() \
+ public:
+
//--------------------------------------------------------------------------------------
#define INTERFACE_14(KIND, \
N_0, AN_0, T_0, C_0, \
//--------------------------------------------------------------------------------------
bool ModelHighAPI_RefAttr::isEmpty() const
{
- return !(myAttribute && myObject);
+ return !(myAttribute || myObject);
}
//--------------------------------------------------------------------------------------
{
theAttribute->clear();
- if(!theValue.empty()) {
+ if(!theValue.empty() && theAttribute->selectionType().empty()) {
const ModelHighAPI_Selection& aSelection = theValue.front();
GeomAPI_Shape::ShapeType aSelectionType = getShapeType(aSelection);
theAttribute->setSelectionType(strByShapeType(aSelectionType));
std::list<ObjectPtr>::iterator allIter = allObjects.begin();
for(; allIter != allObjects.end(); allIter++) {
ObjectPtr anObject = *allIter;
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+ if (aFeature && aFeature->getKind() == "SketchConstraintCoincidenceInternal")
+ continue; // no need to dump and check internal constraints
+
if (theCompare) {
std::map<std::string, ModelHighAPI_FeatureStore>::iterator
anObjFind = aDocFind->second.find(anObject->data()->name());
theStore[theDocName][anObject->data()->name()] = ModelHighAPI_FeatureStore(anObject);
}
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
if (aFeature) {
// iterate all results of this feature
std::list<ResultPtr> allResults;
if (aDump.get()) {
aDump->string("file_path")->setValue(theFilename);
aDump->string("file_format")->setValue("py");
- aDump->boolean("topological_naming")->setValue(theSelectionType & CHECK_NAMING);
- aDump->boolean("geometric_selection")->setValue(theSelectionType & CHECK_GEOMETRICAL);
- aDump->boolean("weak_naming")->setValue(theSelectionType & CHECK_WEAK);
+ aDump->boolean("topological_naming")->setValue((theSelectionType & CHECK_NAMING) != 0);
+ aDump->boolean("geometric_selection")->setValue((theSelectionType & CHECK_GEOMETRICAL) != 0);
+ aDump->boolean("weak_naming")->setValue((theSelectionType & CHECK_WEAK) != 0);
}
bool isProblem = !aDump.get() || !aDump->error().empty(); // after "finish" dump will be removed
if (isProblem && aDump.get()) {
# additional preprocessor / compiler flags
ADD_DEFINITIONS(${QT_DEFINITIONS})
+SET(UPDATE_TRANSLATION OFF)
+
SET(PROJECT_HEADERS
ModuleBase.h
ModuleBase_ActionInfo.h
ModuleBase_IStepPrs.cpp
)
+SET(TEXT_RESOURCES
+ ModuleBase_msg_fr.ts
+)
+
SET(PROJECT_LIBRARIES
Config
Events
# sources / moc wrappings
QT_WRAP_MOC(PROJECT_AUTOMOC ${PROJECT_MOC_HEADERS})
-#QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+IF (${UPDATE_TRANSLATION})
+ SET(PROJECT_FILES ${PROJECT_SOURCES} ${PROJECT_HEADERS} )
+ QT5_CREATE_TRANSLATION(QM_RESOURCES
+ ${PROJECT_FILES}
+ ${TEXT_RESOURCES}
+ OPTIONS -extensions cpp -no-recursive
+ )
+ELSE(${UPDATE_TRANSLATION})
+ 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})
-#SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES} ${PROJECT_RESOURCES})
+SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES} ${PROJECT_RESOURCES})
INCLUDE_DIRECTORIES(
${OpenCASCADE_INCLUDE_DIR}
ENDIF(${HAVE_SALOME})
ADD_DEFINITIONS(-DMODULEBASE_EXPORTS ${OpenCASCADE_DEFINITIONS})
-ADD_LIBRARY(ModuleBase SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${PROJECT_AUTOMOC})
+ADD_LIBRARY(ModuleBase SHARED
+ ${PROJECT_SOURCES}
+ ${PROJECT_HEADERS}
+ ${PROJECT_AUTOMOC}
+ ${TEXT_RESOURCES}
+ ${QM_RESOURCES}
+)
+
TARGET_LINK_LIBRARIES(ModuleBase GeomAPI ${PROJECT_LIBRARIES})
INSTALL(TARGETS ModuleBase DESTINATION ${SHAPER_INSTALL_BIN})
+INSTALL(FILES ${QM_RESOURCES} DESTINATION ${SHAPER_INSTALL_QM_RESOURCES})
#include "ModuleBase_IPropertyPanel.h"
#include "ModuleBase_PageWidget.h"
#include "ModuleBase_ModelDialogWidget.h"
+#include "ModuleBase_Tools.h"
#include <ModelAPI_Session.h>
#include <ModelAPI_Events.h>
myActiveWidget(0)
{
ModuleBase_WidgetFactory aFactory(myDescription, myWorkshop);
- std::string aTitle = aFactory.widgetAPI()->getProperty(FEATURE_TEXT);
+ QString aTitle = ModuleBase_Tools::translate("ModuleBase_Dialog",
+ aFactory.widgetAPI()->getProperty(FEATURE_TEXT));
- setWindowTitle(aTitle.c_str());
+ setWindowTitle(aTitle);
SessionPtr aMgr = ModelAPI_Session::get();
std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
#define ModuleBase_IViewer_H
#include "ModuleBase.h"
+
#include <QObject>
#include <QMap>
#include <AIS_InteractiveContext.hxx>
class QKeyEvent;
class QContextMenuEvent;
class ModuleBase_IViewWindow;
+#ifdef HAVE_SALOME
+class OCCViewer_Fitter;
+#else
+class AppElements_Fitter;
+#endif
/**
* \ingroup GUI
myShowHighlight = false;
}
+#ifdef HAVE_SALOME
+ virtual void setFitter(OCCViewer_Fitter* theFitter) = 0;
+ virtual OCCViewer_Fitter* fitter() const = 0;
+#else
+ virtual void setFitter(AppElements_Fitter* theFitter) = 0;
+ virtual AppElements_Fitter* fitter() const = 0;
+#endif
+
static Handle(Prs3d_Drawer) DefaultHighlightDrawer;
+
signals:
/// Signal emited when last view window is closed
void lastViewClosed();
Events_InfoMessage ModuleBase_ModelWidget::getValueStateError() const
{
Events_InfoMessage aMessage;
+ aMessage.setContext(context());
ModuleBase_ModelWidget::ValueState aState = getValueState();
if (aState != ModuleBase_ModelWidget::Stored) {
{
theWidget->setFocus();
// rectangle of focus is not visible on tool button widgets
- theWidget->repaint();
+ theWidget->update();
#ifdef DEBUG_SET_FOCUS
qDebug(QString("setFocus: %1").arg(theInfo).toStdString().c_str());
#endif
if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
aNotActivatedDocWrn =
- QObject::tr("Selected objects can be used in Part documents which are not loaded:%1.\n")
+ QObject::tr("Selected objects can be used in Part documents which are not loaded: %1.\n")
.arg(aNotActivatedNames.c_str());
}
aMainLay->addWidget(myResultLabel);
myEditor = new ExpressionEditor(this);
myEditor->setMinimumHeight(20);
- myEditor->setPlaceHolderText( QString::fromStdString( thePlaceHolder ) );
+ myEditor->setPlaceHolderText( translate( thePlaceHolder ) );
aMainLay->addWidget(myEditor);
this->setLayout(aMainLay);
if (theType == WDG_GROUP) {
QString aGroupName = qs(myWidgetApi->getProperty(CONTAINER_PAGE_NAME));
ModuleBase_PageGroupBox* aPage = new ModuleBase_PageGroupBox(theParent);
- aPage->setTitle(aGroupName);
+ aPage->setTitle(ModuleBase_Tools::translate(
+ myWidgetApi->myFeatureId, aGroupName.toStdString()));
aResult = aPage;
}
else if (theType == WDG_OPTIONALBOX) {
#include <ModuleBase_Tools.h>
#include <ModelAPI_AttributeString.h>
+#include <Config_Translator.h>
+#include <QTextCodec>
#include <QLabel>
#include <QVBoxLayout>
DataPtr aData = myFeature->data();
AttributeStringPtr aStrAttr = aData->string(attributeID());
if (aStrAttr.get()) {
- std::string aMsg;
+ QString aText;
if (aStrAttr.get()) {
- aMsg = aStrAttr->value();
+ if (aStrAttr->isUValue()) { // already translated text
+ char16_t* aStr = aStrAttr->valueU();
+ std::wstring aWStr((wchar_t*)aStr);
+ static const int aBufSize = 1000;
+ static char aMBStr[aBufSize];
+ size_t aLen = wcstombs(aMBStr, aWStr.c_str(), aBufSize);
+ std::string aCodec = Config_Translator::codec("");
+ aText = QTextCodec::codecForName(aCodec.c_str())->toUnicode(aMBStr);
+ } else {
+ std::string aMsg = aStrAttr->value();
+ aText = ModuleBase_Tools::translate(myFeature->getKind(), aMsg);
+ }
}
- QString aText = ModuleBase_Tools::translate(myFeature->getKind(), aMsg);
myLabel->setText(aText);
}
return true;
aLayout->setContentsMargins(0, 0, 0, 0);
aLayout->setSpacing(0);
- QString aText = QString::fromStdString(theData->widgetLabel());
+ QString aText = translate(theData->widgetLabel());
QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
- QString aToolTip = QString::fromStdString(theData->widgetTooltip());
+ QString aToolTip = translate(theData->widgetTooltip());
myLabel = new ModuleBase_LabelValue(theParent, aText, aToolTip, aLabelIcon);
bool isOk;
if (!aLabelIcon.isEmpty())
aLabel->setPixmap(ModuleBase_IconFactory::loadPixmap(aLabelIcon));
- myLineEdit = new CustomLineEdit( this, QString::fromStdString( thePlaceHolder ) );
+ myLineEdit = new CustomLineEdit( this, translate( thePlaceHolder ) );
// Here we do not use the Qt's standard method setPlaceHolderText() since it
// draws the place holder only if there is no focus on widget;
// we would like to see the place holder in the case of empty text
}
}
- QString aToolTip = QString::fromStdString(theData->widgetTooltip());
+ QString aToolTip = translate(theData->widgetTooltip());
QString anObjName = QString::fromStdString(attributeID());
myListView = new ModuleBase_ListView(this, anObjName, aToolTip);
connect(myListView->getControl(), SIGNAL(itemSelectionChanged()), SLOT(onListSelection()));
}
// We have to call repaint because sometimes the List control is not updated
- myListView->getControl()->repaint();
+ myListView->getControl()->update();
}
//********************************************************************
myXSpin = new ModuleBase_ParamSpinBox(this);
myXSpin->setAcceptVariables(aAcceptVariables);
- myXSpin->setToolTip("X coordinate");
+ myXSpin->setToolTip(tr("X coordinate"));
myXSpin->setValue(myDefaultValue[0]);
QLabel* aXLbl = new QLabel(this);
aXLbl->setPixmap(QPixmap(":pictures/x_size.png"));
myYSpin = new ModuleBase_ParamSpinBox(this);
myYSpin->setAcceptVariables(aAcceptVariables);
- myYSpin->setToolTip("Y coordinate");
+ myYSpin->setToolTip(tr("Y coordinate"));
myYSpin->setValue(myDefaultValue[1]);
QLabel* aYLbl = new QLabel(this);
aYLbl->setPixmap(QPixmap(":pictures/y_size.png"));
myZSpin = new ModuleBase_ParamSpinBox(this);
myZSpin->setAcceptVariables(aAcceptVariables);
- myZSpin->setToolTip("Z coordinate");
+ myZSpin->setToolTip(tr("Z coordinate"));
myZSpin->setValue(myDefaultValue[2]);
QLabel* aZLbl = new QLabel(this);
aZLbl->setPixmap(QPixmap(":pictures/z_size.png"));
QRadioButton* aButton;
if (theIcon.isNull()) {
aButton = new QRadioButton(theName, aWgt);
- aButton->setToolTip(theTooltip);
+ aButton->setToolTip(translate(theTooltip.toStdString()));
}
else {
aButton = new QRadioButton(aWgt);
- aButton->setToolTip(theName);
+ aButton->setToolTip(translate(theName.toStdString()));
}
aLay->addStretch();
aLay->addWidget(aButton);
#include <StdSelect_BRepOwner.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
+#include <TopExp_Explorer.hxx>
#include <QLayout>
#include <QPushButton>
myListIO.Clear();
myShowBtn->setChecked(false);
}
- aCtx->UpdateCurrentViewer();
+ myWorkshop->viewer()->update();
}
SelectorFeature = FeaturePtr();
AttributeId = "";
}
}
}
- aCtx->UpdateCurrentViewer();
+ myWorkshop->viewer()->update();
}
void ModuleBase_WidgetSelectionFilter::updateSelectBtn()
}
}
+void replaceSubShapesByResult(QList<ModuleBase_ViewerPrsPtr>& theResults, int theShapeType)
+{
+ QMap<ObjectPtr, QList<GeomShapePtr>> myResShapes;
+ // Sort sub-shapes by result
+ foreach (ModuleBase_ViewerPrsPtr aPrs, theResults) {
+ if (myResShapes.contains(aPrs->object()))
+ myResShapes[aPrs->object()].append(aPrs->shape());
+ else {
+ QList<GeomShapePtr> aShapes;
+ aShapes << aPrs->shape();
+ myResShapes[aPrs->object()] = aShapes;
+ }
+ }
+ // Find Results to replace by whole result
+ QList<GeomShapePtr> aShapes;
+ QList<ObjectPtr> aToReplace;
+ std::list<GeomShapePtr> aSubShapes;
+ foreach(ObjectPtr aObj, myResShapes.keys()) {
+ aShapes = myResShapes[aObj];
+ ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+ TopTools_MapOfShape aShapesMap;
+ if (aRes.get()) {
+ GeomShapePtr aSubShape = aRes->shape();
+ const TopoDS_Shape& aShape = aSubShape->impl<TopoDS_Shape>();
+ for (TopExp_Explorer anExp(aShape, (TopAbs_ShapeEnum)theShapeType);
+ anExp.More(); anExp.Next()) {
+ aShapesMap.Add(anExp.Current());
+ }
+ }
+ if (aShapes.count() == aShapesMap.Size())
+ aToReplace.append(aObj);
+ }
+ // Replace the found results
+ QList<ModuleBase_ViewerPrsPtr>::iterator aIt;
+ foreach(ObjectPtr aObj, aToReplace) {
+ for (aIt = theResults.begin(); aIt != theResults.end(); aIt++) {
+ if ((*aIt)->object() == aObj) {
+ theResults.removeAll(*aIt);
+ aIt--;
+ }
+ }
+ ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aObj));
+ theResults.append(aValue);
+ }
+}
+
void ModuleBase_WidgetSelectionFilter::onFeatureAccepted()
{
AttributePtr aAttr = mySelectorFeature->attribute(mySelectorAttribute);
AttributeSelectionListPtr aSelListAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(aAttr);
aSelListAttr->clear();
+ if (aSelListAttr->isWholeResultAllowed())
+ replaceSubShapesByResult(myValues, selectionType(aSelListAttr->selectionType().c_str()));
foreach(ModuleBase_ViewerPrsPtr aPrs, myValues) {
aSelListAttr->append(aPrs->object(), aPrs->shape());
}
{
GeomShapePtr aShape = myWorkshop->selection()->getShape(thePrs);
ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
- bool aValid = acceptSubShape(aShape, aResult);
+ bool aValid = aResult.get();
+ if (!isWholeResultAllowed())
+ aValid = acceptSubShape(aShape, aResult);
if (aValid) {
// In order to avoid selection of the same object
aSelectAttr->removeTemporaryValues();
}
}
+
+//********************************************************************
+bool ModuleBase_WidgetSelector::isWholeResultAllowed() const
+{
+ AttributePtr anAttribute = attribute();
+ if (anAttribute.get()) {
+ AttributeSelectionListPtr aSelAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(anAttribute);
+ if (aSelAttr.get())
+ return aSelAttr->isWholeResultAllowed();
+ }
+ return false;
+}
/// a shape. If the attribute do not uses the shape, it is empty
virtual QList<std::shared_ptr<ModuleBase_ViewerPrs>> getAttributeSelection() const;
+ virtual bool isWholeResultAllowed() const;
+
protected:
/// Returns true if envent is processed. The default implementation is empty, returns false.
virtual bool processSelection();
bool isNameUpdated = false;
AttributeSelectionPtr aSelect = aData->selection(attributeID());
if (aSelect) {
- myTextLine->setText(QString::fromStdString(aSelect->namingName(getDefaultValue())));
+ std::string aDefault = translate(getDefaultValue()).toStdString();
+ myTextLine->setText(QString::fromStdString(aSelect->namingName(aDefault)));
isNameUpdated = true;
}
if (!isNameUpdated) {
myTextLine->setText(QString::fromStdString(anAttrName));
}
else {
- myTextLine->setText(getDefaultValue().c_str());
+ myTextLine->setText(translate(getDefaultValue()));
}
}
}
{
int aSuperCount =
ModuleBase_PagedContainer::addPage(thePage, theName, theCaseId, theIcon, theTooltip);
- myCombo->addItem(theName);
+ myCombo->addItem(translate(theName.toStdString()));
int aResultCount = myCombo->count();
if (aResultCount == 2)
myCombo->show();
{
ModuleBase_PagedContainer::addPage(thePage, theName, theCaseId, theIcon, theTooltip);
QFrame* aFrame = dynamic_cast<QFrame*>(thePage);
- myToolBox->addItem(aFrame, theName, theIcon );
+ myToolBox->addItem(aFrame, translate(theName.toStdString()), theIcon );
return myToolBox->count();
}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+ <context>
+ <name>ExpressionEditor</name>
+ <message>
+ <location filename="ModuleBase_WidgetExprEditor.cpp" line="65"/>
+ <source>Ctrl+Space</source>
+ <comment>Complete</comment>
+ <translation>Ctrl+Espace</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_FilterItem</name>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="192"/>
+ <source>Reverse the filter</source>
+ <translation>Inverser le filtre</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="202"/>
+ <source>Delete the filter</source>
+ <translation>Supprimer le filtre</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_FilterStarter</name>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="95"/>
+ <source>Selection by filters</source>
+ <translation>Sélection par filtres</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_ListView</name>
+ <message>
+ <location filename="ModuleBase_ListView.cpp" line="45"/>
+ <source>Copy</source>
+ <translation>Copie</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_ListView.cpp" line="51"/>
+ <source>Delete</source>
+ <translation>Effacer</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_PreferencesDlg</name>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="251"/>
+ <source>Edit preferences</source>
+ <translation>Modifier les préférences</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="267"/>
+ <source>Default</source>
+ <translation>Défaut</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="285"/>
+ <source>Desktop</source>
+ <translation>Bureau</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="291"/>
+ <source>Module</source>
+ <translation>Module</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="300"/>
+ <source>Viewer</source>
+ <translation>Vue</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="303"/>
+ <source>Horizontal gradient</source>
+ <translation>Dégradé horizontal</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="303"/>
+ <source>Vertical gradient</source>
+ <translation>Gradient vertical</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="303"/>
+ <source>First diagonal gradient</source>
+ <translation>Premier gradient en diagonale</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="304"/>
+ <source>Second diagonal gradient</source>
+ <translation>Deuxième gradient diagonal</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="304"/>
+ <source>First corner gradient</source>
+ <translation>Premier angle de dégradé</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="305"/>
+ <source>Second corner gradient</source>
+ <translation>Deuxième angle du dégradé</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="305"/>
+ <source>Third corner gradient</source>
+ <translation>Troisième angle de dégradé</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="306"/>
+ <source>Fourth corner gradient</source>
+ <translation>Quatrième angle</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="312"/>
+ <source>Background</source>
+ <translation>Arrière-plan</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="316"/>
+ <source>Viewer 3d</source>
+ <translation>Vue 3d</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="328"/>
+ <source>Default selection</source>
+ <translation>Sélection par défaut</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="330"/>
+ <source>Faces</source>
+ <translation>Faces</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="333"/>
+ <source>Edges</source>
+ <translation>Arêtes</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="336"/>
+ <source>Vertices</source>
+ <translation>Sommets</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="340"/>
+ <source>Selection sensitivity</source>
+ <translation>Sensibilité de sélection</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="342"/>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="344"/>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="347"/>
+ <source>Additional highlighting</source>
+ <translation>Mise en évidence supplémentaire</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="349"/>
+ <source>In 3d mode</source>
+ <translation>En mode 3D</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="351"/>
+ <source>In 2d mode</source>
+ <translation>En mode 2D</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="354"/>
+ <source>Color scale</source>
+ <translation>Échelle de couleur</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="356"/>
+ <source>X position</source>
+ <translation>Position X</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="361"/>
+ <source>Y position</source>
+ <translation>Position Y</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="366"/>
+ <source>Width</source>
+ <translation>Largeur</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="371"/>
+ <source>Height</source>
+ <translation>Hauteur</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="376"/>
+ <source>Intervals number</source>
+ <translation>Nombre d'intervalles</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="381"/>
+ <source>Text height</source>
+ <translation>Hauteur du texte</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="386"/>
+ <source>Text color</source>
+ <translation>Couleur du texte</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="392"/>
+ <source>Main menu</source>
+ <translation>Menu principal</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="394"/>
+ <source>Size</source>
+ <translation>Taille</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="397"/>
+ <source>Number of rows</source>
+ <translation>Nombre de rangées</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Preferences.cpp" line="404"/>
+ <source>Show Status Bar</source>
+ <translation>Afficher la barre d'état</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_WidgetFileSelector</name>
+ <message>
+ <location filename="ModuleBase_WidgetFileSelector.cpp" line="70"/>
+ <source>Select file...</source>
+ <translation>Choisir le dossier...</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_WidgetMultiSelector</name>
+ <message>
+ <location filename="ModuleBase_WidgetMultiSelector.cpp" line="133"/>
+ <source>Type</source>
+ <translation>Type</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetMultiSelector.cpp" line="188"/>
+ <source>Show only</source>
+ <translation>Montrer seulement</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetMultiSelector.cpp" line="199"/>
+ <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>
+ <location filename="ModuleBase_WidgetPointInput.cpp" line="63"/>
+ <source>X coordinate</source>
+ <translation>Coordonnée X</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetPointInput.cpp" line="71"/>
+ <source>Y coordinate</source>
+ <translation>Coordonnée Y</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetPointInput.cpp" line="79"/>
+ <source>Z coordinate</source>
+ <translation>Coordonnée Z</translation>
+ </message>
+ </context>
+ <context>
+ <name>ModuleBase_WidgetSelectionFilter</name>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="242"/>
+ <source>Filters</source>
+ <translation>Filtres</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="253"/>
+ <source>Add new filter...</source>
+ <translation>Ajouter un nouveau filtre...</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="276"/>
+ <source>Select</source>
+ <translation>Sélectionner</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="287"/>
+ <source>Number of selected objects:</source>
+ <translation>Nombre d'objets sélectionnés:</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="293"/>
+ <source>Show only</source>
+ <translation>Montrer seulement</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="551"/>
+ <location filename="ModuleBase_WidgetSelectionFilter.cpp" line="631"/>
+ <source>Selection is empty</source>
+ <translation>La sélection est vide</translation>
+ </message>
+ </context>
+ <context>
+ <name>QObject</name>
+ <message>
+ <location filename="ModuleBase_Tools.cpp" line="942"/>
+ <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>
+ <location filename="ModuleBase_Tools.cpp" line="1011"/>
+ <source>Delete features</source>
+ <translation>Supprimer les fonctionnalités</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Tools.cpp" line="1021"/>
+ <source>The following parts will be deleted: %1.
+</source>
+ <translation>Les pièces suivantes seront supprimées : %1.
+
+</translation>
+ </message>
+ <message>
+ <location filename="ModuleBase_Tools.cpp" line="1039"/>
+ <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 <QMessageBox>
+#include <ModuleBase_Tools.h>
+
#include <string>
#include <set>
#include <sstream>
std::string aNotActivatedNames;
if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
- QMessageBox::StandardButton aRes = QMessageBox::warning(0, QObject::tr("Warning"),
- QObject::tr("Selected objects can be used in Part documents which are not loaded: "
- "%1. Whould you like to continue?").arg(aNotActivatedNames.c_str()),
- QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
+ static const std::string aMsgContext("ParametersPlugin");
+ static const std::string aMsgText =
+ "Selected objects can be used in Part documents which are not loaded: " +
+ std::string("%1. Would you like to continue?");
+ Events_InfoMessage aMsg(aMsgContext, aMsgText);
+ aMsg.arg(aNotActivatedNames.c_str());
+ QMessageBox::StandardButton aRes =
+ QMessageBox::warning(0, ModuleBase_Tools::translate(aMsgContext, "Warning"),
+ ModuleBase_Tools::translate(aMsg),
+ QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
if (aRes != QMessageBox::Yes) {
setParameterName(aResultParameter, aMessage->oldName());
return;
const char* NoName = "<NoName>";
const char* NoValue = "<NoValue>";
-const char* NotValid = "<NotValid>";
/*!
* \ingroup GUI
myTable = new ParametersPlugin_TreeWidget(this);
myTable->setColumnCount(4);
QStringList aHeaders;
- aHeaders << tr("Name") << tr("Expression") << tr("Result") << tr("Comment");
+ aHeaders << translate("Name") << translate("Expression")
+ << translate("Result") << translate("Comment");
myTable->setHeaderLabels(aHeaders);
myTable->setColumnWidth(Col_Name, 200);
myTable->setColumnWidth(Col_Equation, 100);
// Define root nodes
QStringList aNames;
- aNames<<tr("Parameters");
+ aNames<<translate("Parameters");
myParameters = new QTreeWidgetItem(aNames);
myParameters->setFlags(Qt::ItemIsEnabled);
myTable->addTopLevelItem(myParameters);
aNames.clear();
- aNames<<tr("Features");
+ aNames<<translate("Features");
myFeatures = new QTreeWidgetItem(aNames);
myFeatures->setFlags(Qt::ItemIsEnabled);
myTable->addTopLevelItem(myFeatures);
aBtnLayout->addStretch();
- myAddBtn = new QPushButton(tr("Add"), this);
+ myAddBtn = new QPushButton(translate("Add"), this);
connect(myAddBtn, SIGNAL(clicked(bool)), SLOT(onAdd()));
aBtnLayout->addWidget(myAddBtn);
- myInsertBtn = new QPushButton(tr("Insert"), this);
+ myInsertBtn = new QPushButton(translate("Insert"), this);
connect(myInsertBtn, SIGNAL(clicked(bool)), SLOT(onInsert()));
aBtnLayout->addWidget(myInsertBtn);
- myRemoveBtn = new QPushButton(tr("Remove"), this);
+ myRemoveBtn = new QPushButton(translate("Remove"), this);
connect(myRemoveBtn, SIGNAL(clicked(bool)), SLOT(onRemove()));
aBtnLayout->addWidget(myRemoveBtn);
QWidget* aBtnParentWgt = myOkCancelBtn->parentWidget();
QHBoxLayout* aBtnParentLayout = dynamic_cast<QHBoxLayout*>(aBtnParentWgt->layout());
- QPushButton* aPreviewBtn = new QPushButton(tr("See preview"), aBtnParentWgt);
+ QPushButton* aPreviewBtn = new QPushButton(translate("See preview"), aBtnParentWgt);
aBtnParentLayout->insertWidget(0, aPreviewBtn);
aBtnParentLayout->insertStretch(1, 1);
connect(aPreviewBtn, SIGNAL(clicked(bool)), SLOT(onShowPreview()));
int aId = 0;
foreach(FeaturePtr aFeature, myParametersList) {
if (!aValidator.isValid(aFeature->attribute(aAttrId), aArgs, aErr)) {
- // TODO(spo): translate
- QMessageBox::warning(this, tr("Warning"), aErr.messageString().c_str());
+ QMessageBox::warning(this, translate("Warning"), aErr.messageString().c_str());
selectItemScroll(myParameters->child(aId));
return false;
}
std::string aName = aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->value();
if (aName.empty()) {
- aValues << NoName;
+ aValues << translate(NoName);
} else
aValues << aName.c_str();
std::string aExpr = aParameter->string(ParametersPlugin_Parameter::EXPRESSION_ID())->value();
if (aName.empty()) {
- aValues << NoValue;
+ aValues << translate(NoValue);
} else
aValues << aExpr.c_str();
aText.replace(" ", "");
}
if (hasName(aText)) {
- myMessage = tr("Name '%1' already exists.").arg(aText);
+ myMessage = translate("Name '%1' already exists.").arg(aText);
QTimer::singleShot(50, this, SLOT(sendWarning()));
return;
}
QTreeWidgetItem* ParametersPlugin_WidgetParamsMgr::createNewItem(QTreeWidgetItem* theParent) const
{
QStringList aValues;
- aValues << NoName;
- aValues << NoValue;
+ aValues << translate(NoName);
+ aValues << translate(NoValue);
QTreeWidgetItem* aItem = new QTreeWidgetItem(aValues);
if (theParent == myParameters) {
void ParametersPlugin_WidgetParamsMgr::sendWarning()
{
- QMessageBox::warning(this, tr("Warning"), myMessage);
+ QMessageBox::warning(this, translate("Warning"), myMessage);
QTreeWidgetItem* aItem = myTable->currentItem();
if (aItem)
myTable->editItem(aItem);
for(int i = 0; i < myParameters->childCount(); i++) {
aItem = myParameters->child(i);
if ((aItem->text(Col_Name) == NoName) ||
- (aItem->text(Col_Equation) == NoValue) ||
+ (aItem->text(Col_Equation) == translate(NoValue)) ||
(!ModelAPI_Expression::isVariable(aItem->text(Col_Name).toStdString())) ) {
return false;
}
--- /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>
# additional preprocessor / compiler flags
ADD_DEFINITIONS(${QT_DEFINITIONS})
+SET(UPDATE_TRANSLATION OFF)
+
SET(PROJECT_HEADERS
PartSet.h
PartSet_Constants.h
PartSet_icons.qrc
)
-#SET(TEXT_RESOURCES
-# PartSet_msg_fr.ts
-#)
+SET(TEXT_RESOURCES
+ PartSet_msg_fr.ts
+)
SET(PROJECT_LIBRARIES
ModuleBase
# sources / rcc wrappings
QT_ADD_RESOURCES(PROJECT_COMPILED_RESOURCES ${PROJECT_RESOURCES})
-#QT4_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
-#QT4_CREATE_TRANSLATION(QM_RESOURCES
-# ${PROJECT_SOURCES}
-# ${TEXT_RESOURCES}
-# OPTIONS -extensions cpp -no-recursive
-# )
-
-#SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${PROJECT_COMPILED_RESOURCES} ${QM_RESOURCES})
-SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${PROJECT_COMPILED_RESOURCES})
-#SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES} ${PROJECT_RESOURCES})
-SOURCE_GROUP ("Resource Files" FILES ${PROJECT_RESOURCES})
+
+IF (${UPDATE_TRANSLATION})
+ SET(PROJECT_FILES ${PROJECT_SOURCES} ${ROJECT_HEADERS} )
+ QT5_CREATE_TRANSLATION(QM_RESOURCES
+ ${PROJECT_FILES}
+ ${TEXT_RESOURCES}
+ OPTIONS -extensions cpp -no-recursive
+ )
+ELSE(${UPDATE_TRANSLATION})
+ 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})
+#SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${PROJECT_COMPILED_RESOURCES})
+SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES} ${PROJECT_RESOURCES})
+#SOURCE_GROUP ("Resource Files" FILES ${PROJECT_RESOURCES})
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/XGUI
${PROJECT_SOURCE_DIR}/src/Config
${PROJECT_HEADERS}
${PROJECT_COMPILED_RESOURCES}
${PROJECT_AUTOMOC}
-# ${TEXT_RESOURCES}
-# ${QM_RESOURCES}
+ ${TEXT_RESOURCES}
+ ${QM_RESOURCES}
)
# The Qt5Widgets_LIBRARIES variable also includes QtGui and QtCore
ADD_DEPENDENCIES(PartSet ModuleBase)
INSTALL(TARGETS PartSet DESTINATION ${SHAPER_INSTALL_BIN})
-#INSTALL(FILES ${QM_RESOURCES} DESTINATION bin)
+INSTALL(FILES ${QM_RESOURCES} DESTINATION ${SHAPER_INSTALL_QM_RESOURCES})
PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
XGUI_Workshop* aWorkshop = workshop();
aRedisplayed = aWorkshop->displayer()->displayAIS(myPresentations[theFlag],
- false/*load object in selection*/, false);
+ false/*load object in selection*/, 0, false);
aContext->SetZLayer(anOperationPrs, aModule->getVisualLayerId());
isModified = true;
}
else
myPresentations[aPrs->object()] = aList;
foreach(AISObjectPtr anAIS, aList) {
- aDisplayer->displayAIS(anAIS, false);
+ aDisplayer->displayAIS(anAIS, false, 0, false);
aWorkshop->selectionActivate()->activateAIS(anAIS->impl<Handle(AIS_InteractiveObject)>(),
TopAbs_VERTEX, false);
}
#include "PartSet_Filters.h"
#include "PartSet_FilterInfinite.h"
+#ifdef _DEBUG
+#include <QDebug>
+#endif
+
#include <PartSetPlugin_Remove.h>
#include <PartSetPlugin_Part.h>
#include <PartSetPlugin_Duplicate.h>
#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
-#ifdef _DEBUG
-#include <QDebug>
-#endif
-
/*!Create and return new instance of XGUI_Module*/
extern "C" PARTSET_EXPORT ModuleBase_IModule* createModule(ModuleBase_IWorkshop* theWshop)
{
ModuleBase_OperationFeature* aFOperation =
dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
if (aFOperation) {
- myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, true);
- myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeResults, true);
+ myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, false);
+ myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeResults, false);
}
}
ModuleBase_OperationFeature* aFOperation =
dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
if (aFOperation) {
- myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, true);
- myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeResults, true);
+ myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, false);
+ myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeResults, false);
}
}
connect(aLabelWgt, SIGNAL(showConstraintToggled(int, bool)),
mySketchMgr, SLOT(onShowConstraintsToggle(int, bool)));
connect(aLabelWgt, SIGNAL(showFreePoints(bool)), mySketchMgr, SLOT(onShowPoints(bool)));
+ connect(aLabelWgt, SIGNAL(autoConstraints(bool)),
+ sketchReentranceMgr(), SLOT(onAutoConstraints(bool)));
aLabelWgt->setShowPointsState(mySketchMgr->isShowFreePointsShown());
aWgt = aLabelWgt;
} else if (theType == "sketch-2dpoint_selector") {
XGUI_Displayer* aDisplayer = aWorkshop->displayer();
QObjectPtrList aObjects = aDisplayer->displayedObjects();
bool aHidden;
+ bool aUpdateViewer = false;
foreach(ObjectPtr aObj, aObjects) {
aHidden = !aObj->data() || !aObj->data()->isValid() ||
aObj->isDisabled() || (!aObj->isDisplayed());
- if (!aHidden)
+ if (!aHidden) {
aDisplayer->redisplay(aObj, false);
+ aUpdateViewer = true;
+ }
}
- aDisplayer->updateViewer();
+ if (aUpdateViewer)
+ aDisplayer->updateViewer();
// Update tree items if they are expanded
if (needUpdate) {
- aTreeView->viewport()->repaint(aTreeView->viewport()->rect());
+ aTreeView->viewport()->update(aTreeView->viewport()->rect());
}
} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)) {
std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aUpdMsg =
// change deviation coefficient to provide more precise circle
// as there is no result, the shape is processed to correct deviation. To be unified
ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, aDrawer);
+ Handle(Prs3d_Drawer) aHighlightDrawer = DynamicHilightAttributes();
+ if (!aHighlightDrawer.IsNull())
+ ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, aHighlightDrawer);
if (myUseAISWidth) {
Handle(AIS_InteractiveObject) anIO = anIter.Value();
PartSet_Module* aModule = module();
CompositeFeaturePtr aSketch = aModule->sketchMgr()->activeSketch();
if (aSketch.get()) {
- std::string aDOFMessage = aSketch->string(SketchPlugin_Sketch::SOLVER_DOF())->value();
- myIsFullyConstrained = QString(aDOFMessage.c_str()).contains("DoF = 0");
+ QString aDOFMessage(aSketch->string(SketchPlugin_Sketch::SOLVER_DOF())->value().c_str());
+ if (aDOFMessage.contains('=')) {
+ // to support old data
+ aDOFMessage =
+ aDOFMessage.right(aDOFMessage.length() - aDOFMessage.lastIndexOf('=')).trimmed();
+ }
+ myIsFullyConstrained = (aDOFMessage == "0");
}
}
}
myXYPlane = createPreviewPlane(anOrigin, aXYDir, aB);
}
XGUI_Displayer* aDisp = XGUI_Tools::workshop(theWorkshop)->displayer();
- aDisp->displayAIS(myYZPlane, true, false);
- aDisp->displayAIS(myXZPlane, true, false);
- aDisp->displayAIS(myXYPlane, true, false);
+ aDisp->displayAIS(myYZPlane, true, 0, false);
+ aDisp->displayAIS(myXZPlane, true, 0, false);
+ aDisp->displayAIS(myXYPlane, true, 0, false);
myPreviewDisplayed = true;
}
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintDistance.h>
#include <SketchPlugin_ConstraintParallel.h>
: QObject(theModule), myModule(theModule), myIsEditLaunching(false), myIsDragging(false),
myDragDone(false), myIsMouseOverWindow(false),
myIsMouseOverViewProcessed(true), myPreviousUpdateViewerEnabled(true),
- myIsPopupMenuActive(false), myExternalPointsMgr(0)
+ myIsPopupMenuActive(false), myExternalPointsMgr(0), myNoDragMoving(false)
{
ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
ModuleBase_IViewer* aViewer = anIWorkshop->viewer();
ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
ModuleBase_IViewer* aViewer = aWorkshop->viewer();
- if (!aViewer->canDragByMouse())
- return;
+ //if (!aViewer->canDragByMouse())
+ // return;
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
(getCurrentOperation());
if (!aFOperation)
return;
- if (aFOperation->isEditOperation()) {
+ bool isEditing = aFOperation->isEditOperation();
+ bool aCanDrag = aViewer->canDragByMouse();
+
+ //if (!aViewer->canDragByMouse() && isEditing) {
+ // // Do not edit by dragging
+ // return;
+ //}
+
+ if (isEditing) {
// If the current widget is a selector, do nothing, it processes the mouse press
ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
if(anActiveWidget && anActiveWidget->isViewerSelector()) {
if ((!isSketchOpe) && (!isSketcher))
return;
- bool isEditing = aFOperation->isEditOperation();
-
// Ignore creation sketch operation
if ((!isSketcher) && (!isEditing))
return;
- Handle(AIS_InteractiveContext) aContext = aViewer->AISContext();
- // Remember highlighted objects for editing
- ModuleBase_ISelection* aSelect = aWorkshop->selection();
-
bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
storeSelection(aHasShift ? ST_SelectAndHighlightType : ST_HighlightType, myCurrentSelection);
get2dPoint(theWnd, theEvent, myCurrentPoint);
if (isSketcher) {
- myIsDragging = true;
- myDragDone = false;
-
+ if (aCanDrag) {
+ myIsDragging = true;
+ myDragDone = false;
+ }
myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
launchEditing();
if (aFeature.get() != NULL) {
myIsEditLaunching = !myModule->sketchReentranceMgr()->isInternalEditActive();
aFOperation->commit();
- myIsDragging = true;
- myDragDone = false;
-
+ if (aCanDrag) {
+ myIsDragging = true;
+ myDragDone = false;
+ }
myPreviousDrawModeEnabled = aViewer->enableDrawMode(false);
launchEditing();
myIsEditLaunching = aPrevLaunchingState;
bool aWasDragging = myIsDragging;
myIsDragging = false;
- if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
+ if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent)) {
return;
-
+ }
// if mouse is pressed when it was over view and at release the mouse is out of view, do nothing
- if (!myIsMouseOverViewProcessed)
+ if (!myIsMouseOverViewProcessed) {
return;
-
+ }
ModuleBase_IViewer* aViewer = aWorkshop->viewer();
- if (!aViewer->canDragByMouse())
- return;
- ModuleBase_Operation* aOp = getCurrentOperation();
+ //if (!aViewer->canDragByMouse())
+ // return;
+ ModuleBase_OperationFeature* aOp =
+ dynamic_cast<ModuleBase_OperationFeature*>(getCurrentOperation());
if (aOp) {
- if (isNestedSketchOperation(aOp)) {
- // Only for sketcher operations
- if (aWasDragging) {
- if (myDragDone) {
- /// the previous selection is lost by mouse release in the viewer(Select method), but
- /// it is still stored in myCurrentSelection. So, it is possible to restore selection
- /// It is important for drag(edit with mouse) of sketch entities.
- restoreSelection(myCurrentSelection);
- myCurrentSelection.clear();
+ bool aStartNoDragOperation = !aViewer->canDragByMouse() && aOp->isEditOperation();
+ if (aStartNoDragOperation || myNoDragMoving) {
+ // Process edit operation without dragging
+ if (myCurrentSelection.size() > 0)
+ myNoDragMoving = !myNoDragMoving;
+ else
+ myNoDragMoving = false;
+ if (myNoDragMoving)
+ return;
+ else {
+ restoreSelection(myCurrentSelection);
+ myCurrentSelection.clear();
+ }
+ }
+ else {
+ if (isNestedSketchOperation(aOp)) {
+ // Only for sketcher operations
+ if (aWasDragging) {
+ if (myDragDone) {
+ /// the previous selection is lost by mouse release in the viewer(Select method), but
+ /// it is still stored in myCurrentSelection. So, it is possible to restore selection
+ /// It is important for drag(edit with mouse) of sketch entities.
+ restoreSelection(myCurrentSelection);
+ myCurrentSelection.clear();
+ }
}
}
}
qDebug(QString("%1").arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
}
#endif
-
if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
return;
+ ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
if (isNestedCreateOperation(getCurrentOperation(), activeSketch())) {
#ifdef DRAGGING_DEBUG
QTime t;
// the feature is to be erased here, but it is correct to call canDisplayObject because
// there can be additional check (e.g. editor widget in distance constraint)
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
+ (getCurrentOperation());
if (aFOperation) {
FeaturePtr aFeature = aFOperation->feature();
visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
}
}
+ aDisplayer->updateViewer();
#ifdef DRAGGING_DEBUG
cout << "Mouse move processing " << t.elapsed() << endl;
#endif
}
//myClickedPoint.clear();
- if (myIsDragging) {
+ if (myIsDragging || myNoDragMoving) {
// 1. the current selection is saved in the mouse press method in order to restore it after
// moving
// 2. the enable selection in the viewer should be temporary switched off in order to ignore
// mouse press signal in the viewer(it call Select for AIS context and the dragged objects are
// deselected). This flag should be restored in the slot, processed the mouse release signal.
-
ModuleBase_Operation* aCurrentOperation = getCurrentOperation();
if (!aCurrentOperation)
return;
if (isSketchOperation(aCurrentOperation))
return; // No edit operation activated
+#ifdef DRAGGING_DEBUG
+ QTime t;
+ t.start();
+#endif
+
Handle(V3d_View) aView = theWnd->v3dView();
gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
Point aMousePnt;
get2dPoint(theWnd, theEvent, aMousePnt);
std::shared_ptr<GeomAPI_Pnt2d> anOriginalPosition = std::shared_ptr<GeomAPI_Pnt2d>(
- new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
+ new GeomAPI_Pnt2d(myCurrentPoint.myCurX, myCurrentPoint.myCurY));
std::shared_ptr<GeomAPI_Pnt2d> aCurrentPosition = std::shared_ptr<GeomAPI_Pnt2d>(
- new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
+ new GeomAPI_Pnt2d(aMousePnt.myCurX, aMousePnt.myCurY));
- ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
- XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
// 3. the flag to disable the update viewer should be set in order to avoid blinking in the
// viewer happens by deselect/select the modified objects. The flag should be restored after
// the selection processing. The update viewer should be also called.
static Events_ID aMoveEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
//static Events_ID aUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
FeatureToSelectionMap::const_iterator anIt = myCurrentSelection.begin(),
- aLast = myCurrentSelection.end();
+ aLast = myCurrentSelection.end();
// 4. the features and attributes modification(move)
bool isModified = false;
for (; anIt != aLast; anIt++) {
// Process selection by attribute: the priority to the attribute
if (!anAttributes.empty()) {
std::set<AttributePtr>::const_iterator anAttIt = anAttributes.begin(),
- anAttLast = anAttributes.end();
+ anAttLast = anAttributes.end();
for (; anAttIt != anAttLast; anAttIt++) {
AttributePtr anAttr = *anAttIt;
if (anAttr.get() == NULL)
bool isImmutable = aPoint->setImmutable(true);
std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
- <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
+ <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
aMessage->setMovedAttribute(aPoint);
aMessage->setOriginalPosition(anOriginalPosition);
aMessage->setCurrentPosition(aCurrentPosition);
}
}
}
- } else {
+ }
+ else {
// Process selection by feature
std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
if (aSketchFeature) {
std::shared_ptr<ModelAPI_ObjectMovedMessage> aMessage = std::shared_ptr
- <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
+ <ModelAPI_ObjectMovedMessage>(new ModelAPI_ObjectMovedMessage(this));
aMessage->setMovedObject(aFeature);
aMessage->setOriginalPosition(anOriginalPosition);
aMessage->setCurrentPosition(aCurrentPosition);
aDisplayer->enableUpdateViewer(isEnableUpdateViewer);
aDisplayer->updateViewer();
+#ifdef DRAGGING_DEBUG
+ cout << "Mouse move processing " << t.elapsed() << endl;
+#endif
+
myDragDone = true;
myCurrentPoint = aMousePnt;
}
return (theId == SketchPlugin_Line::ID()) ||
(theId == SketchPlugin_Point::ID()) ||
(theId == SketchPlugin_Arc::ID()) ||
- (theId == SketchPlugin_Circle::ID());
+ (theId == SketchPlugin_Circle::ID()) ||
+ (theId == SketchPlugin_Ellipse::ID()) ||
+ (theId == SketchPlugin_EllipticArc::ID());
}
bool PartSet_SketcherMgr::isExternalFeature(const FeaturePtr& theFeature)
myExternalPointsMgr = new PartSet_ExternalPointsMgr(myModule->workshop(), myCurrentSketch);
workshop()->viewer()->set2dMode(true);
+
+ PartSet_Fitter* aFitter = new PartSet_Fitter(this);
+ myModule->workshop()->viewer()->setFitter(aFitter);
}
void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation)
{
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
+ PartSet_Fitter* aFitter = (PartSet_Fitter*)myModule->workshop()->viewer()->fitter();
+ myModule->workshop()->viewer()->setFitter(0);
+ delete aFitter;
+
myIsMouseOverWindow = false;
myIsConstraintsShown[PartSet_Tools::Geometrical] = true;
myIsConstraintsShown[PartSet_Tools::Dimensional] = true;
}
onShowPoints(false);
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myModule->workshop());
-
DataPtr aData = myCurrentSketch->data();
if (!aData->isValid()) {
XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
if (aToUpdate)
aViewer->update();
}
+
+
+void PartSet_Fitter::fitAll(Handle(V3d_View) theView)
+{
+ CompositeFeaturePtr aSketch = mySketchMgr->activeSketch();
+
+ ModuleBase_IWorkshop* aWorkshop = mySketchMgr->module()->workshop();
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(aWorkshop);
+ XGUI_Displayer* aDisplayer = aConnector->workshop()->displayer();
+
+ Bnd_Box aBndBox;
+ int aNumberOfSubs = aSketch->numberOfSubs();
+ double aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+ for (int i = 0; i < aNumberOfSubs; i++) {
+ FeaturePtr aFeature = aSketch->subFeature(i);
+ if (aDisplayer->isVisible(aFeature)) {
+ AISObjectPtr aAisPtr = aDisplayer->getAISObject(aFeature);
+ Handle(AIS_InteractiveObject) aAisObj = aAisPtr->impl<Handle(AIS_InteractiveObject)>();
+ if (!aAisObj->IsInfinite()) {
+ Bnd_Box aBox;
+ aAisObj->BoundingBox(aBox);
+ aBndBox.Add(aBox);
+ }
+ }
+ else {
+ std::list<ResultPtr> aResults = aFeature->results();
+ std::list<ResultPtr>::const_iterator aIt;
+ ResultPtr aRes;
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+ aRes = (*aIt);
+ if (aRes->isDisplayed()) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRes);
+ if (aFeature.get()) {
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+ if (aSPFeature.get()) {
+ bool isAxiliary =
+ aSPFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value();
+ if (!(aSPFeature->isExternal() || isAxiliary)) {
+ GeomShapePtr aShape = aRes->shape();
+ aShape->computeSize(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ Bnd_Box aBox;
+ aBox.Update(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ aBndBox.Add(aBox);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (aBndBox.IsVoid())
+ theView->FitAll();
+ else
+ theView->FitAll(aBndBox, 0.01);
+}
#include <GeomAPI_Pln.h>
+#ifdef HAVE_SALOME
+ #include <OCCViewer_ViewModel.h>
+#else
+ #include <AppElements_Viewer.h>
+#endif
+
+
#include <SelectMgr_IndexedMapOfOwner.hxx>
#include <SelectMgr_ListOfFilter.hxx>
class ModuleBase_Operation;
class XGUI_OperationMgr;
class XGUI_Workshop;
+class XGUI_Displayer;
class PartSet_ExternalPointsMgr;
class AIS_InteractiveObject;
class QMouseEvent;
+class PartSet_SketcherMgr;
+
+#ifdef HAVE_SALOME
+class PartSet_Fitter : public OCCViewer_Fitter
+#else
+class PartSet_Fitter : public AppElements_Fitter
+#endif
+{
+public:
+ PartSet_Fitter(PartSet_SketcherMgr* theSketchMgr):
+ mySketchMgr(theSketchMgr) {}
+
+ /// A method which has top be reimplemented to provide alterantive implementation FitAll command
+ /// \param theView - a view which has to be fit
+ virtual void fitAll(Handle(V3d_View) theView);
+
+private:
+ PartSet_SketcherMgr* mySketchMgr;
+};
+
+
/**
* \ingroup Modules
return myPointsHighlight.size() > 0;
}
+ PartSet_Module* module() const { return myModule; }
+
public slots:
/// Process sketch plane selected event
void onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln);
+ /// The slot is called when user checks "Show free points" button
+ /// \param toShow a state of the check box
void onShowPoints(bool toShow);
private slots:
PartSet_ExternalPointsMgr* myExternalPointsMgr;
QMap<ResultPtr, Handle(AIS_Shape)> myPointsHighlight;
+
+ bool myNoDragMoving;
};
#include "GeomDataAPI_Point2D.h"
+#include "GeomAPI_Lin2d.h"
+#include "GeomAPI_Dir2d.h"
+
#include <ModuleBase_IPropertyPanel.h>
#include <ModuleBase_ISelectionActivate.h>
#include <ModuleBase_OperationFeature.h>
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Trim.h>
#include <SketchPlugin_Split.h>
+#include <SketchPlugin_ConstraintHorizontal.h>
+#include <SketchPlugin_ConstraintVertical.h>
#include <XGUI_Workshop.h>
#include <XGUI_ModuleConnector.h>
myRestartingMode(RM_None),
myIsFlagsBlocked(false),
myIsInternalEditOperation(false),
- myNoMoreWidgetsAttribute("")
+ myNoMoreWidgetsAttribute(""),
+ myIsAutoConstraints(true)
{
}
isStarted = startInternalEdit(thePreviousAttributeID);
}
}
- if (!isStarted)
+ if (!isStarted) {
+ if (myIsAutoConstraints)
+ addConstraints(aFOperation->feature());
aFOperation->commit();
+ }
}
}
}
// returning to the neutral point of the Sketcher or start internal edit
workshop()->selector()->clearSelection();
+ if (myIsAutoConstraints)
+ addConstraints(aFOperation->feature());
+
aFOperation->setEditOperation(true/*, false*/);
createInternalFeature();
aPropertyPanel->setInternalActiveWidget(theWidget);
}
}
+
+void PartSet_SketcherReentrantMgr::onAutoConstraints(bool isOn)
+{
+ myIsAutoConstraints = isOn;
+}
+
+void PartSet_SketcherReentrantMgr::addConstraints(const FeaturePtr& theFeature)
+{
+ if (theFeature->getKind() != SketchPlugin_Line::ID())
+ return;
+
+ static GeomDir2dPtr myHorDir(new GeomAPI_Dir2d(1, 0));
+ static GeomDir2dPtr myVertDir(new GeomAPI_Dir2d(0, 1));
+
+ std::shared_ptr<ModelAPI_Data> aData = theFeature->data();
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aData->attribute(SketchPlugin_Line::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aData->attribute(SketchPlugin_Line::END_ID()));
+ if (aPoint1.get() && aPoint2.get()) {
+ GeomLine2dPtr aLine(new GeomAPI_Lin2d(aPoint1->pnt(), aPoint2->pnt()));
+ GeomDir2dPtr aDir = aLine->direction();
+ double aHorAngle = fabs(myHorDir->angle(aDir));
+ double aVertAngle = fabs(myVertDir->angle(aDir));
+ if (aHorAngle > M_PI/2.)
+ aHorAngle = M_PI - aHorAngle;
+ if (aVertAngle > M_PI/2.)
+ aVertAngle = M_PI - aVertAngle;
+
+ double aTolerance = Config_PropManager::real(SKETCH_TAB_NAME, "angular_tolerance");
+ CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+ FeaturePtr aFeature;
+ if (aHorAngle < aTolerance)
+ // Add horizontal constraint
+ aFeature = aSketch->addFeature(SketchPlugin_ConstraintHorizontal::ID());
+ else if (aVertAngle < aTolerance)
+ // Add vertical constraint
+ aFeature = aSketch->addFeature(SketchPlugin_ConstraintVertical::ID());
+
+ if (aFeature.get()) {
+ aFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(
+ theFeature->firstResult());
+ }
+ }
+}
/// \param theMessage a message of reentrant operation
void setReentrantPreSelection(const std::shared_ptr<Events_Message>& theMessage);
+ bool isAutoConstraints() const { return myIsAutoConstraints; }
+
+
+public slots:
+ /// The slot is called when user checks "Automatic constraints" button
+ /// \param isOn a state of the check box
+ void onAutoConstraints(bool isOn);
+
+
private slots:
/// SLOT, that is called by a widget activating in the property panel
/// If the 'internal' edit operation is started, it activates the first widget selection
/// \param theSourceFeature a source feature
/// \param theNewFeature a new feature
/// \param theSketch an active sketch
- /// \param isTemporary is used to do not create additional features(e.g. coicidence for line)
+ /// \param isTemporary is used to do not create additional features(e.g. coincidence for line)
/// \return true is something is copied
static bool copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
const FeaturePtr& theNewFeature,
void setInternalActiveWidget(ModuleBase_ModelWidget* theWidget);
+ void addConstraints(const FeaturePtr& theFeature);
+
private:
ModuleBase_IWorkshop* myWorkshop; /// the workshop
ObjectPtr mySelectedObject; /// cashed selected object
std::shared_ptr<ModelAPI_Attribute> mySelectedAttribute; /// cashed selected attribute
std::shared_ptr<GeomAPI_Pnt2d> myClickedSketchPoint; /// cashed clicked point
+
+ bool myIsAutoConstraints;
};
#endif
return false;
GeomAPI_Edge aEdge1(aShape);
- if (aEdge1.isLine() || aEdge1.isArc()) {
- if (aList.size() == 2) {
- // Check second selection
- aPrs = aList.last();
- const GeomShapePtr& aShape2 = aPrs->shape();
- if (!aShape2.get() || aShape2->isNull() || aShape2->shapeType() != GeomAPI_Shape::EDGE)
- return false;
- GeomAPI_Edge aEdge2(aShape2);
-
- if (aEdge1.isLine() && aEdge2.isArc())
- return true;
- else if (aEdge1.isArc() && aEdge2.isLine())
- return true;
- else
- return false;
- } else
- return true;
+ if (aList.size() == 2) {
+ // Check second selection
+ aPrs = aList.last();
+ const GeomShapePtr& aShape2 = aPrs->shape();
+ if (!aShape2.get() || aShape2->isNull() || aShape2->shapeType() != GeomAPI_Shape::EDGE)
+ return false;
+ GeomAPI_Edge aEdge2(aShape2);
+
+ if (aEdge1.isLine() && aEdge2.isLine())
+ return false;
}
- return false;
}
+ return true;
}
bool PartSet_AngleSelection::isValid(const ModuleBase_ISelection* theSelection,
aType = 1;
else if (aType != 1)
return false;
- } else if (aEdge.isCircle()) {
+ } else if (aEdge.isCircle() || aEdge.isArc()) {
if (aCount == 1)
aType = 2;
else if (aType != 2)
return false;
- } else if (aEdge.isArc()) {
+ } else if (aEdge.isEllipse()) {
if (aCount == 1)
aType = 3;
else if (aType != 3)
// the control should accept the focus, so the boolean flag is corrected to be true
myIsObligatory = true;
- QString aPageName = QString::fromStdString(theData->getProperty(CONTAINER_PAGE_NAME));
+ QString aPageName = translate(theData->getProperty(CONTAINER_PAGE_NAME));
myGroupBox = new QGroupBox(aPageName, theParent);
myGroupBox->setFlat(false);
AttributePoint2DPtr aFeaturePoint;
if (aFeature->isMacro()) {
// the macro feature will be removed after the operation is stopped, so we need to build
- // coicidence to possible sub-features
+ // coincidence to possible sub-features
aFeaturePoint = findFirstEqualPointInArgumentFeatures(aFeature, aClickedPoint);
}
else {
AttributePoint2DPtr anAttrPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aThisAttr);
if (anAttrPoint.get()) {
// the macro feature will be removed after the operation is stopped, so we need to build
- // coicidence to possible sub-features
+ // coincidence to possible sub-features
aFeaturePoint = findFirstEqualPointInArgumentFeatures(feature(),
anAttrPoint->pnt());
}
ModuleBase_Tools::adjustMargins(aLayout);
- QString aLabelText = QString::fromStdString(theData->widgetLabel());
+ QString aLabelText = translate(theData->widgetLabel());
QString aLabelIcon = QString::fromStdString(theData->widgetIcon());
// Size of the View control
mySizeOfViewWidget = new QWidget(this);
QHBoxLayout* aSizeLayout = new QHBoxLayout(mySizeOfViewWidget);
- aSizeLayout->addWidget(new QLabel("Size of the view", mySizeOfViewWidget));
+ aSizeLayout->addWidget(new QLabel(tr("Size of the view"), mySizeOfViewWidget));
mySizeOfView = new QLineEdit(mySizeOfViewWidget);
QDoubleValidator* aValidator = new QDoubleValidator(0, DBL_MAX, 12, mySizeOfView);
#include "PartSet_Tools.h"
#include "PartSet_Module.h"
#include "PartSet_PreviewPlanes.h"
+#include "PartSet_SketcherReentrantMgr.h"
#include "SketchPlugin_SketchEntity.h"
#include <ModelAPI_ResultBody.h>
#include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeString.h>
#include <ModuleBase_Operation.h>
#include <ModuleBase_ViewerPrs.h>
// Size of the View control
mySizeOfViewWidget = new QWidget(aFirstWgt);
QHBoxLayout* aSizeLayout = new QHBoxLayout(mySizeOfViewWidget);
- aSizeLayout->addWidget(new QLabel("Size of the view", mySizeOfViewWidget));
+ aSizeLayout->addWidget(new QLabel(tr("Size of the view"), mySizeOfViewWidget));
mySizeOfView = new QLineEdit(mySizeOfViewWidget);
QDoubleValidator* aValidator = new QDoubleValidator(0, DBL_MAX, 12, mySizeOfView);
mySizeOfView->setValidator(aValidator);
aSizeLayout->addWidget(mySizeOfView);
- QString aText = QString::fromStdString(theData->getProperty("title"));
+ QString aText = translate(theData->getProperty("title"));
QLabel* aLabel = new QLabel(aText, aFirstWgt);
aLabel->setWordWrap(true);
- QString aTooltip = QString::fromStdString(theData->getProperty("tooltip"));
+ QString aTooltip = translate(theData->getProperty("tooltip"));
aLabel->setToolTip(aTooltip);
aLabel->setIndent(5);
connect(myShowPoints, SIGNAL(toggled(bool)), this, SIGNAL(showFreePoints(bool)));
aLayout->addWidget(myShowPoints);
+ myAutoConstraints = new QCheckBox(tr("Automatic constraints"), this);
+ myAutoConstraints->setToolTip(tr("Automatic vertical and horizontal constraints"));
+ connect(myAutoConstraints, SIGNAL(toggled(bool)), this, SIGNAL(autoConstraints(bool)));
+ aLayout->addWidget(myAutoConstraints);
+
QPushButton* aPlaneBtn = new QPushButton(tr("Change sketch plane"), aSecondWgt);
connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
aLayout->addWidget(aPlaneBtn);
+ myDoFLabel = new QLabel("", aSecondWgt);
+ aLayout->addWidget(myDoFLabel);
+
myStackWidget->addWidget(aSecondWgt);
//setLayout(aLayout);
void PartSet_WidgetSketchLabel::activateCustom()
{
+ PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+ if (aModule) {
+ bool isBlocked = myAutoConstraints->blockSignals(true);
+ myAutoConstraints->setChecked(aModule->sketchReentranceMgr()->isAutoConstraints());
+ myAutoConstraints->blockSignals(isBlocked);
+ }
+
std::shared_ptr<GeomAPI_Pln> aPlane = plane();
if (aPlane.get()) {
myStackWidget->setCurrentIndex(1);
myShowPoints->setChecked(theState);
myShowPoints->blockSignals(aBlock);
}
+
+bool PartSet_WidgetSketchLabel::restoreValueCustom()
+{
+ if (myFeature.get()) {
+ CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+ if (aSketch.get() && (aSketch->numberOfSubs() > 0)) {
+ AttributeStringPtr aDOFStr = aSketch->string("SolverDOF");
+ if (aDOFStr.get()) {
+ QString aVal(aDOFStr->value().c_str());
+ if (aVal.contains('=')) {
+ // to support old data
+ aVal = aVal.right(aVal.length() - aVal.lastIndexOf('='));
+ }
+ int aDoF = aVal.toInt();
+ if (aDoF == 0) {
+ myDoFLabel->setText(tr("Sketch is fully fixed (DoF = 0)"));
+ } else {
+ myDoFLabel->setText(tr("DoF (degrees of freedom) = ") + aVal);
+ }
+ }
+ }
+ else {
+ myDoFLabel->setText("");
+ }
+ }
+ return true;
+}
/// \param theState a state of the check box
void showConstraintToggled(int theType, bool theState);
+ /// The signal is emitted when user checks "Show free points" button
+ /// \param toShow a state of the check box
void showFreePoints(bool toShow);
+ /// The signal is emitted when user checks "Automatic constraints" button
+ /// \param isOn a state of the check box
+ void autoConstraints(bool isOn);
+
protected:
/// Creates a backup of the current values of the attribute
/// It should be realized in the specific widget because of different
return true;
}
- virtual bool restoreValueCustom()
- {
- return true;
- }
+ virtual bool restoreValueCustom();
/// The methiod called when widget is activated
virtual void activateCustom();
QCheckBox* myViewInverted;
QCheckBox* myRemoveExternal;
QCheckBox* myShowPoints;
+ QCheckBox* myAutoConstraints;
QMap<PartSet_Tools::ConstraintVisibleState, QCheckBox*> myShowConstraints;
QLineEdit* mySizeOfView; ///< Value of square of size of View
QStackedWidget* myStackWidget;
+ QLabel* myDoFLabel;
+
bool myOpenTransaction;
bool myIsSelection;
};
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+ <name>PartSet_MenuMgr</name>
+ <message>
+ <location filename="PartSet_MenuMgr.cpp" line="91"/>
+ <location filename="PartSet_MenuMgr.cpp" line="529"/>
+ <source>Auxiliary</source>
+ <translation>Auxiliaire</translation>
+ </message>
+ <message>
+ <location filename="PartSet_MenuMgr.cpp" line="95"/>
+ <location filename="PartSet_MenuMgr.cpp" line="100"/>
+ <source>Activate</source>
+ <translation>Activer</translation>
+ </message>
+ <message>
+ <location filename="PartSet_MenuMgr.cpp" line="104"/>
+ <source>Edit...</source>
+ <translation>Modifier...</translation>
+ </message>
+ <message>
+ <location filename="PartSet_MenuMgr.cpp" line="185"/>
+ <location filename="PartSet_MenuMgr.cpp" line="324"/>
+ <location filename="PartSet_MenuMgr.cpp" line="528"/>
+ <source>Detach</source>
+ <translation>Détacher</translation>
+ </message>
+ <message>
+ <location filename="PartSet_MenuMgr.cpp" line="317"/>
+ <source>Detach %1</source>
+ <translation>Détachez %1</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetPoint2D</name>
+ <message>
+ <location filename="PartSet_WidgetPoint2d.cpp" line="118"/>
+ <source>X</source>
+ <translation>X</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetPoint2d.cpp" line="134"/>
+ <source>Y</source>
+ <translation>Y</translation>
+ </message>
+</context>
+<context>
+ <name>PartSet_WidgetSketchCreator</name>
+ <message>
+ <location filename="PartSet_WidgetSketchCreator.cpp" line="91"/>
+ <source>Size of the view</source>
+ <translation>Taille de la vue</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchCreator.cpp" line="546"/>
+ <source>Apply current feature</source>
+ <translation>Appliquer la fonctionnalité actuelle</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchCreator.cpp" line="547"/>
+ <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>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="106"/>
+ <source>Size of the view</source>
+ <translation>Taille de la vue</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="127"/>
+ <source>Remove external dependencies</source>
+ <translation>Supprimer les dépendances externes</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="141"/>
+ <source>Sketcher plane</source>
+ <translation>Plan du Sketcher</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="144"/>
+ <source>Reversed</source>
+ <translation>Renversé</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="148"/>
+ <source>Set plane view</source>
+ <translation>Définir la vue plane</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="155"/>
+ <source>Show geometrical constraints</source>
+ <translation>Afficher les contraintes géométriques</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="156"/>
+ <source>Show dimensional constraints</source>
+ <translation>Afficher les contraintes dimensionnelles</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="157"/>
+ <source>Show existing expressions</source>
+ <translation>Afficher les expressions existantes</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="172"/>
+ <source>Show free points</source>
+ <translation>Afficher les points libres</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="176"/>
+ <source>Automatic constraints</source>
+ <translation>Contraintes automatiques</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="177"/>
+ <source>Automatic vertical and horizontal constraints</source>
+ <translation>Automatique des contraintes verticales et horizontales</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="181"/>
+ <source>Change sketch plane</source>
+ <translation>Changer le plan d'esquisse</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="753"/>
+ <source>Sketch is fully fixed (DoF = 0)</source>
+ <translation>L'esquisse est entièrement fixée (DdL = 0)</translation>
+ </message>
+ <message>
+ <location filename="PartSet_WidgetSketchLabel.cpp" line="755"/>
+ <source>DoF (degrees of freedom) = </source>
+ <translation>DdL (degrés de liberté) = </translation>
+ </message>
+</context>
+<context>
+ <name>QObject</name>
+ <message>
+ <location filename="PartSet_TreeNodes.cpp" line="402"/>
+ <source>Parameters</source>
+ <translation>Paramètres</translation>
+ </message>
+ <message>
+ <location filename="PartSet_TreeNodes.cpp" line="404"/>
+ <source>Constructions</source>
+ <translation>Constructions</translation>
+ </message>
+ <message>
+ <location filename="PartSet_TreeNodes.cpp" line="406"/>
+ <source>Parts</source>
+ <translation>Pièces</translation>
+ </message>
+ <message>
+ <location filename="PartSet_TreeNodes.cpp" line="408"/>
+ <source>Results</source>
+ <translation>Résultats</translation>
+ </message>
+ <message>
+ <location filename="PartSet_TreeNodes.cpp" line="410"/>
+ <source>Fields</source>
+ <translation>Champs</translation>
+ </message>
+ <message>
+ <location filename="PartSet_TreeNodes.cpp" line="412"/>
+ <source>Groups</source>
+ <translation>Groupes</translation>
+ </message>
+</context>
+</TS>
plugin-PartSet.xml
)
+SET(TEXT_RESOURCES
+ PartSetPlugin_msg_fr.ts
+)
+
+SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
+
ADD_DEFINITIONS(-DPARTSETPLUGIN_EXPORTS)
-ADD_LIBRARY(PartSetPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
+ADD_LIBRARY(PartSetPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES} ${TEXT_RESOURCES})
TARGET_LINK_LIBRARIES(PartSetPlugin ${PROJECT_LIBRARIES} ModelAPI)
INCLUDE_DIRECTORIES(
)
INSTALL(TARGETS PartSetPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
-INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+INSTALL(FILES ${XML_RESOURCES} ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/PartSet)
--- /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>
torus_widget.xml
)
+SET(TEXT_RESOURCES
+ PrimitivesPlugin_msg_fr.ts
+)
+
+SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
+
INCLUDE_DIRECTORIES(
../ModelAPI
../GeomAPI
)
ADD_DEFINITIONS(-DPRIMITIVESPLUGIN_EXPORTS)
-ADD_LIBRARY(PrimitivesPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES})
+ADD_LIBRARY(PrimitivesPlugin MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${XML_RESOURCES} ${TEXT_RESOURCES})
TARGET_LINK_LIBRARIES(PrimitivesPlugin ${PROJECT_LIBRARIES})
INSTALL(TARGETS PrimitivesPlugin DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
-INSTALL(FILES ${XML_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+INSTALL(FILES ${XML_RESOURCES} ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Primitives)
--- /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>
#
import ModelHighAPI
+from GeomAPI import *
from GeomDataAPI import *
from ModelAPI import *
import math
return thePoint
elif issubclass(type(thePoint), GeomDataAPI_Point2D):
return [thePoint.x(), thePoint.y()]
+ elif issubclass(type(thePoint), GeomAPI_Pnt2d):
+ return [thePoint.x(), thePoint.y()]
else:
aFeature = toSketchFeature(thePoint)
aPoint = geomDataAPI_Point2D(aFeature.attribute("PointCoordinates"))
# additional preprocessor / compiler flags
ADD_DEFINITIONS(${QT_DEFINITIONS})
+SET(UPDATE_TRANSLATION OFF)
+
SET(PROJECT_HEADERS
SHAPER_SHAPERGUI.h
SHAPERGUI.h
SHAPERGUI_OCCSelector.h
SHAPERGUI_SalomeViewer.h
SHAPERGUI_NestedButton.h
- SHAPERGUI_ToolbarsMgr.h
+ SHAPERGUI_ToolbarsMgr.h
)
SET(PROJECT_MOC_HEADERS
SHAPERGUI_DataModel.h
SHAPERGUI_NestedButton.h
SHAPERGUI_SalomeViewer.h
- SHAPERGUI_ToolbarsMgr.h
+ SHAPERGUI_ToolbarsMgr.h
)
# sources / moc wrappings
SHAPERGUI_OCCSelector.cpp
SHAPERGUI_SalomeViewer.cpp
SHAPERGUI_NestedButton.cpp
- SHAPERGUI_ToolbarsMgr.cpp
+ SHAPERGUI_ToolbarsMgr.cpp
)
SET(PROJECT_RESOURCES
resources/shaper.png
)
+SET(TEXT_RESOURCES
+ SHAPERGUI_msg_fr.ts
+)
+
+IF (${UPDATE_TRANSLATION})
+ SET(PROJECT_FILES ${PROJECT_SOURCES} ${PROJECT_HEADERS} )
+ QT5_CREATE_TRANSLATION(QM_RESOURCES
+ ${PROJECT_FILES}
+ ${TEXT_RESOURCES}
+ OPTIONS -extensions cpp -no-recursive
+ )
+ELSE(${UPDATE_TRANSLATION})
+ IF(${MAKE_TRANSLATION})
+ QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
+ ENDIF(${MAKE_TRANSLATION})
+ENDIF(${UPDATE_TRANSLATION})
+
+
SET(PROJECT_LIBRARIES
Events
Config
${PROJECT_SOURCES}
${PROJECT_HEADERS}
${PROJECT_AUTOMOC}
+ ${QM_RESOURCES}
)
ADD_DEPENDENCIES(SHAPER XGUI)
INSTALL(TARGETS SHAPER DESTINATION ${SHAPER_INSTALL_BIN})
INSTALL(FILES ${PROJECT_RESOURCES} DESTINATION ${SHAPER_INSTALL_RESOURCES})
+INSTALL(FILES ${QM_RESOURCES} DESTINATION ${SHAPER_INSTALL_QM_RESOURCES})
}
}
+void SHAPERGUI_SalomeViewer::setFitter(OCCViewer_Fitter* theFitter)
+{
+ if (mySelector)
+ mySelector->viewer()->setFitter(theFitter);
+}
+
+OCCViewer_Fitter* SHAPERGUI_SalomeViewer::fitter() const
+{
+ if (mySelector)
+ return mySelector->viewer()->fitter();
+ return 0;
+}
//void SHAPERGUI_SalomeViewer::Zfitall()
// \param theText is a title
virtual void setColorScaleTitle(const QString& theText);
+ virtual void setFitter(OCCViewer_Fitter* theFitter);
+ virtual OCCViewer_Fitter* fitter() const;
+
// Fit all along Z (perpendicular to display)
//virtual void Zfitall();
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+ <context>
+ <name>SHAPERGUI</name>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="170"/>
+ <source>Inspection</source>
+ <translation>Inspection</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="171"/>
+ <source>Information</source>
+ <translation>Information</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="176"/>
+ <source>Show inspection window</source>
+ <translation>Afficher la fenêtre d'inspection</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="177"/>
+ <source>What Is</source>
+ <translation>Qu’est-ce que c’est</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="183"/>
+ <source>Inspection tool</source>
+ <translation>Outil d'inspection</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="191"/>
+ <source>Edit toolbars of the module</source>
+ <translation>Editer les barres d'outils du module</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="193"/>
+ <source>Edit toolbars...</source>
+ <translation>Editer les barres d'outils...</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="775"/>
+ <source>Viewer</source>
+ <translation>Vue</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="777"/>
+ <source>Default selection</source>
+ <translation>Sélection par défaut</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="779"/>
+ <source>Faces</source>
+ <translation>Faces</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="782"/>
+ <source>Edges</source>
+ <translation>Arêtes</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="785"/>
+ <source>Vertices</source>
+ <translation>Sommets</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="789"/>
+ <source>Selection sensitivity</source>
+ <translation>Sensibilité de sélection</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="791"/>
+ <source>Vertex</source>
+ <translation>Sommet</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="793"/>
+ <source>Edge</source>
+ <translation>Bord</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="796"/>
+ <source>Additional highlighting</source>
+ <translation>Mise en évidence supplémentaire</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="798"/>
+ <source>In 3d mode</source>
+ <translation>En mode 3D</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="800"/>
+ <source>In 2d mode</source>
+ <translation>En mode 2D</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="803"/>
+ <source>Color scale</source>
+ <translation>Échelle de couleur</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="805"/>
+ <source>X position</source>
+ <translation>Position X</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="810"/>
+ <source>Y position</source>
+ <translation>Position Y</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="815"/>
+ <source>Width</source>
+ <translation>Largeur</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="820"/>
+ <source>Height</source>
+ <translation>Hauteur</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="825"/>
+ <source>Intervals number</source>
+ <translation>Nombre d'intervalles</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="830"/>
+ <source>Text height</source>
+ <translation>Hauteur du texte</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI.cpp" line="835"/>
+ <source>Text color</source>
+ <translation>Couleur du texte</translation>
+ </message>
+ </context>
+ <context>
+ <name>SHAPERGUI_ToolbarItemsDlg</name>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="268"/>
+ <source>Edit toolbar</source>
+ <translation>Editer la barre d'outils</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="278"/>
+ <source>Toolbar name:</source>
+ <translation>Nom de la barre d'outils:</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="298"/>
+ <source>Out of toolbars:</source>
+ <translation>Hors des barres d'outils:</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="333"/>
+ <source>In the toolbar:</source>
+ <translation>Dans la barre d'outils:</translation>
+ </message>
+ </context>
+ <context>
+ <name>SHAPERGUI_ToolbarsDlg</name>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="88"/>
+ <source>Toolbars</source>
+ <translation>Barres d'outils</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="103"/>
+ <source>Toolbars:</source>
+ <translation>Barres d'outils:</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="115"/>
+ <source>Number of commands out of toolbars:</source>
+ <translation>Nombre de commandes hors des barres d'outils:</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="125"/>
+ <source>Add...</source>
+ <translation>Ajouter...</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="126"/>
+ <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>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="130"/>
+ <source>Edit...</source>
+ <translation>Modifier...</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="131"/>
+ <source>Edit currently selected toolbar</source>
+ <translation>Modifier la barre d'outils actuellement sélectionnée</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="135"/>
+ <source>Delete</source>
+ <translation>Effacer</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="136"/>
+ <source>Delete currently selected toolbar</source>
+ <translation>Supprimer la barre d'outils actuellement sélectionnée</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="141"/>
+ <source>Reset</source>
+ <translation>Réinitialiser</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="142"/>
+ <source>Restore default toolbars structure</source>
+ <translation>Restaurer la structure des barres d'outils par défaut</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="163"/>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="172"/>
+ <source>Create toolbar</source>
+ <translation>Créer une barre d'outils</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="163"/>
+ <source>Name of a new toolbar</source>
+ <translation>Nom d'une nouvelle barre d'outils</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="171"/>
+ <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>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="205"/>
+ <source>Toolbar %1 will be deleted. Continue?</source>
+ <translation>La barre d'outils %1 sera supprimée. Continuez ?</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="206"/>
+ <source>Delete toolbar</source>
+ <translation>Supprimer la barre d'outils</translation>
+ </message>
+ <message>
+ <location filename="SHAPERGUI_ToolbarsMgr.cpp" line="224"/>
+ <source> (%1 commands)</source>
+ <translation>AA</translation>
+ </message>
+ </context>
+</TS>
<section name="resources">
<!-- Module resources -->
<parameter name="SHAPER" value="%SHAPER_ROOT_DIR%/share/salome/resources/shaper"/>
+ <parameter name="SHAPERGUI" value="%SHAPER_ROOT_DIR%/share/salome/resources/shaper"/>
+ <parameter name="ModuleBase" value="%SHAPER_ROOT_DIR%/share/salome/resources/shaper"/>
+ <parameter name="PartSet" value="%SHAPER_ROOT_DIR%/share/salome/resources/shaper"/>
+ <parameter name="XGUI" value="%SHAPER_ROOT_DIR%/share/salome/resources/shaper"/>
</section>
<section name="Viewer" >
<!-- Viewer preferences -->
SketchAPI_Circle.h
SketchAPI_Constraint.h
SketchAPI_ConstraintAngle.h
+ SketchAPI_Ellipse.h
+ SketchAPI_EllipticArc.h
SketchAPI_IntersectionPoint.h
SketchAPI_Line.h
SketchAPI_MacroArc.h
SketchAPI_MacroCircle.h
+ SketchAPI_MacroEllipse.h
+ SketchAPI_MacroEllipticArc.h
SketchAPI_Mirror.h
- SketchAPI_Sketch.h
- SketchAPI_SketchEntity.h
SketchAPI_Point.h
SketchAPI_Projection.h
SketchAPI_Rectangle.h
SketchAPI_Rotation.h
+ SketchAPI_Sketch.h
+ SketchAPI_SketchEntity.h
SketchAPI_Translation.h
)
SketchAPI_Circle.cpp
SketchAPI_Constraint.cpp
SketchAPI_ConstraintAngle.cpp
+ SketchAPI_Ellipse.cpp
+ SketchAPI_EllipticArc.cpp
SketchAPI_IntersectionPoint.cpp
SketchAPI_Line.cpp
SketchAPI_MacroArc.cpp
SketchAPI_MacroCircle.cpp
+ SketchAPI_MacroEllipse.cpp
+ SketchAPI_MacroEllipticArc.cpp
SketchAPI_Mirror.cpp
- SketchAPI_Sketch.cpp
- SketchAPI_SketchEntity.cpp
SketchAPI_Point.cpp
SketchAPI_Projection.cpp
SketchAPI_Rectangle.cpp
SketchAPI_Rotation.cpp
+ SketchAPI_Sketch.cpp
+ SketchAPI_SketchEntity.cpp
SketchAPI_Translation.cpp
)
// standard definitions
%include "typemaps.i"
%include "std_list.i"
+%include "std_pair.i"
%include "std_shared_ptr.i"
+// function with named parameters
+%feature("kwargs") SketchAPI_Ellipse::construction;
+%feature("kwargs") SketchAPI_EllipticArc::construction;
+
// shared pointers
%shared_ptr(SketchAPI_Arc)
%shared_ptr(SketchAPI_MacroArc)
%shared_ptr(SketchAPI_Circle)
%shared_ptr(SketchAPI_MacroCircle)
+%shared_ptr(SketchAPI_Ellipse)
+%shared_ptr(SketchAPI_MacroEllipse)
+%shared_ptr(SketchAPI_EllipticArc)
+%shared_ptr(SketchAPI_MacroEllipticArc)
%shared_ptr(SketchAPI_Constraint)
%shared_ptr(SketchAPI_ConstraintAngle)
%shared_ptr(SketchAPI_IntersectionPoint)
%template(InterfaceList) std::list<std::shared_ptr<ModelHighAPI_Interface> >;
%template(EntityList) std::list<std::shared_ptr<SketchAPI_SketchEntity> >;
%template(SketchPointList) std::list<std::shared_ptr<SketchAPI_Point> >;
+// std::pair -> []
+%template(PointRefAttrPair) std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>;
%typecheck(SWIG_TYPECHECK_POINTER) std::shared_ptr<ModelAPI_Feature>, const std::shared_ptr<ModelAPI_Feature> & {
std::shared_ptr<ModelAPI_Feature> * temp_feature;
}
}
-%typemap(in) const ModelHighAPI_RefAttr & (ModelHighAPI_RefAttr temp) {
- std::shared_ptr<ModelAPI_Attribute> * temp_attribute;
- std::shared_ptr<ModelAPI_Object> * temp_object;
- std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
- ModelHighAPI_Selection* temp_selection;
- int newmem = 0;
- if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
- if (!temp_selection) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
- return NULL;
- }
- temp = ModelHighAPI_RefAttr(std::shared_ptr<ModelAPI_Object>(temp_selection->resultSubShapePair().first));
- if (newmem & SWIG_CAST_NEW_MEMORY) {
- delete temp_selection;
- }
- $1 = &temp;
- } else
- if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_attribute, $descriptor(std::shared_ptr<ModelAPI_Attribute> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
- if (!temp_attribute) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
- return NULL;
- }
- temp = ModelHighAPI_RefAttr(*temp_attribute);
- if (newmem & SWIG_CAST_NEW_MEMORY) {
- delete temp_attribute;
- }
- $1 = &temp;
- } else
- if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_object, $descriptor(std::shared_ptr<ModelAPI_Object> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
- if (!temp_object) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
- return NULL;
- }
- temp = ModelHighAPI_RefAttr(*temp_object);
- if (newmem & SWIG_CAST_NEW_MEMORY) {
- delete temp_object;
- }
- $1 = &temp;
- } else
- if ((SWIG_ConvertPtrAndOwn($input, (void **)&temp_interface, $descriptor(std::shared_ptr<ModelHighAPI_Interface> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
- if (!temp_interface) {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
- return NULL;
- }
- temp = ModelHighAPI_RefAttr(*temp_interface);
- if (newmem & SWIG_CAST_NEW_MEMORY) {
- delete temp_interface;
- }
- $1 = &temp;
- } else
- if ((SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, SWIG_POINTER_EXCEPTION)) == 0) {
- } else {
- PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
- return NULL;
- }
-}
-
%typemap(in) const std::list<std::shared_ptr<ModelAPI_Object> > & (std::list<std::shared_ptr<ModelAPI_Object> > temp) {
std::shared_ptr<ModelAPI_Object> * temp_object;
std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
}
}
+%typecheck(SWIG_TYPECHECK_POINTER) std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>, const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & {
+ std::shared_ptr<ModelAPI_Attribute> * temp_attribute;
+ std::shared_ptr<ModelAPI_Object> * temp_object;
+ std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
+ ModelHighAPI_Selection* temp_selection;
+ std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>* temp_pair;
+ std::shared_ptr<GeomAPI_Pnt2d> * temp_point;
+ ModelHighAPI_RefAttr temp_refattr;
+ int newmem = 0;
+ std::list<PyObject*> temp_inputlist;
+ if (PySequence_Check($input)) {
+ for (Py_ssize_t i = 0; i < PySequence_Size($input); ++i) {
+ PyObject * temp = PySequence_GetItem($input, i);
+ temp_inputlist.push_back(temp);
+ }
+ } else {
+ temp_inputlist.push_back($input);
+ }
+
+ $1 = 1;
+ for (std::list<PyObject*>::iterator it = temp_inputlist.begin(); it != temp_inputlist.end() && $1; ++it) {
+ PyObject* item = *it;
+
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_selection) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_attribute, $descriptor(std::shared_ptr<ModelAPI_Attribute> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_attribute) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_object, $descriptor(std::shared_ptr<ModelAPI_Object> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_object) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_interface, $descriptor(std::shared_ptr<ModelHighAPI_Interface> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_interface) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_pair, $descriptor(std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_pair) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_point, $descriptor(std::shared_ptr<GeomAPI_Pnt2d> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_point) {
+ $1 = 1;
+ } else {
+ $1 = 0;
+ }
+ } else {
+ $1 = 0;
+ }
+ }
+}
+
+%typemap(in) const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & (std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> temp) {
+ std::shared_ptr<ModelAPI_Attribute> * temp_attribute;
+ std::shared_ptr<ModelAPI_Object> * temp_object;
+ std::shared_ptr<ModelHighAPI_Interface> * temp_interface;
+ ModelHighAPI_Selection* temp_selection;
+ std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>* temp_pair;
+ std::shared_ptr<GeomAPI_Pnt2d> * temp_point = 0;
+ ModelHighAPI_RefAttr temp_refattr;
+ int newmem = 0;
+ std::list<PyObject*> temp_inputlist;
+ if (PySequence_Check($input)) {
+ for (Py_ssize_t i = 0; i < PySequence_Size($input); ++i) {
+ PyObject * temp = PySequence_GetItem($input, i);
+ temp_inputlist.push_back(temp);
+ }
+ } else {
+ temp_inputlist.push_back($input);
+ }
+
+ for (std::list<PyObject*>::iterator it = temp_inputlist.begin(); it != temp_inputlist.end(); ++it) {
+ PyObject* item = *it;
+
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_selection, $descriptor(ModelHighAPI_Selection*), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_selection) {
+ temp_refattr = ModelHighAPI_RefAttr(std::shared_ptr<ModelAPI_Object>(temp_selection->resultSubShapePair().first));
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ delete temp_selection;
+ }
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_attribute, $descriptor(std::shared_ptr<ModelAPI_Attribute> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_attribute) {
+ temp_refattr = ModelHighAPI_RefAttr(*temp_attribute);
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ delete temp_attribute;
+ }
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_object, $descriptor(std::shared_ptr<ModelAPI_Object> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_object) {
+ temp_refattr = ModelHighAPI_RefAttr(*temp_object);
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ delete temp_object;
+ }
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_interface, $descriptor(std::shared_ptr<ModelHighAPI_Interface> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_interface) {
+ temp_refattr = ModelHighAPI_RefAttr(*temp_interface);
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ delete temp_interface;
+ }
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_pair, $descriptor(std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ if (temp_pair) {
+ temp_point = &temp_pair->first;
+ temp_refattr = temp_pair->second;
+ if (newmem & SWIG_CAST_NEW_MEMORY) {
+ delete temp_pair;
+ }
+ }
+ } else
+ if ((SWIG_ConvertPtrAndOwn(item, (void **)&temp_point, $descriptor(std::shared_ptr<GeomAPI_Pnt2d> *), SWIG_POINTER_EXCEPTION, &newmem)) == 0) {
+ // fall through
+ }
+ }
+
+ if (temp_point || !temp_refattr.isEmpty()) {
+ if (temp_point) {
+ temp = std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>(*temp_point, temp_refattr);
+ } else {
+ temp = std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>(std::shared_ptr<GeomAPI_Pnt2d>(), temp_refattr);
+ }
+ if (temp_point && (newmem & SWIG_CAST_NEW_MEMORY)) {
+ delete temp_point;
+ }
+ $1 = &temp;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "argument must be ModelHighAPI_RefAttr, ModelHighAPI_Selection, ModelHighAPI_Interface, ModelAPI_Attribute or ModelAPI_Object.");
+ return NULL;
+ }
+}
+
+// fix compilarion error: 'res*' was not declared in this scope
+%typemap(freearg) const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr> & {}
+
// all supported interfaces (the order is very important according dependencies: base class first)
%include "SketchAPI_SketchEntity.h"
%include "SketchAPI_Point.h"
%include "SketchAPI_MacroCircle.h"
%include "SketchAPI_Arc.h"
%include "SketchAPI_MacroArc.h"
+%include "SketchAPI_Ellipse.h"
+%include "SketchAPI_MacroEllipse.h"
+%include "SketchAPI_EllipticArc.h"
+%include "SketchAPI_MacroEllipticArc.h"
%include "SketchAPI_Projection.h"
%include "SketchAPI_Mirror.h"
%include "SketchAPI_Translation.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 "SketchAPI_Ellipse.h"
+
+#include <GeomAPI_Pnt2d.h>
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+static const std::string AUXILIARY_VALUE = "aux";
+static const std::string MAJOR_AXIS_ID = "majorAxis";
+static const std::string MINOR_AXIS_ID = "minorAxis";
+
+SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature> & theFeature)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ initialize();
+}
+
+SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theMinorRadius)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if(initialize()) {
+ setByCenterFocusAndRadius(theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius);
+ }
+}
+
+SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ double theMinorRadius)
+: SketchAPI_SketchEntity(theFeature)
+{
+ if(initialize()) {
+ setByCenterFocusAndRadius(theCenter, theFocus, theMinorRadius);
+ }
+}
+
+SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theExternal)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ setByExternal(theExternal);
+ }
+}
+
+SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::string& theExternalName)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ setByExternalName(theExternalName);
+ }
+}
+
+SketchAPI_Ellipse::~SketchAPI_Ellipse()
+{
+}
+
+void SketchAPI_Ellipse::setByCenterFocusAndRadius(double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theMinorRadius)
+{
+ fillAttribute(center(), theCenterX, theCenterY);
+ fillAttribute(firstFocus(), theFocusX, theFocusY);
+ fillAttribute(theMinorRadius, myminorRadius);
+
+ execute();
+}
+
+void SketchAPI_Ellipse::setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ double theMinorRadius)
+{
+ fillAttribute(theCenter, mycenter);
+ fillAttribute(theFocus, myfirstFocus);
+ fillAttribute(theMinorRadius, myminorRadius);
+
+ execute();
+}
+
+void SketchAPI_Ellipse::setByExternal(const ModelHighAPI_Selection & theExternal)
+{
+ fillAttribute(theExternal, external());
+ execute();
+}
+
+void SketchAPI_Ellipse::setByExternalName(const std::string & theExternalName)
+{
+ fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
+ execute();
+}
+
+void SketchAPI_Ellipse::setCenter(double theX, double theY)
+{
+ fillAttribute(center(), theX, theY);
+ execute();
+}
+
+void SketchAPI_Ellipse::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
+{
+ fillAttribute(theCenter, mycenter);
+ execute();
+}
+
+void SketchAPI_Ellipse::setFocus(double theX, double theY)
+{
+ fillAttribute(firstFocus(), theX, theY);
+ execute();
+}
+
+void SketchAPI_Ellipse::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
+{
+ fillAttribute(theFocus, myfirstFocus);
+ execute();
+}
+
+void SketchAPI_Ellipse::setMinorRadius(double theMinorRadius)
+{
+ fillAttribute(theMinorRadius, myminorRadius);
+ execute();
+}
+
+static const std::list<PairOfStrings>& ellipseAttrAndDumpNames()
+{
+ static std::list<PairOfStrings> anAttributes;
+ if (anAttributes.empty()) {
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"));
+ }
+ return anAttributes;
+}
+
+static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature)
+{
+ const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
+ if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID())
+ return std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
+ return CompositeFeaturePtr();
+}
+
+static void createInternalConstraint(const CompositeFeaturePtr& theSketch,
+ const AttributePoint2DPtr& thePoint1,
+ const AttributePoint2DPtr& thePoint2)
+{
+ FeaturePtr aConstraint = theSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID());
+ aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(thePoint1);
+ aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(thePoint2);
+ aConstraint->execute();
+}
+
+static void createPoint(const CompositeFeaturePtr& theSketch,
+ const FeaturePtr& theEllipse,
+ const std::string& theCoincident,
+ const std::string& theAuxOrName,
+ std::list<FeaturePtr>& theEntities)
+{
+ if (theAuxOrName.empty())
+ return;
+
+ AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipse->attribute(theCoincident));
+
+ FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID());
+ AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
+ aCoord->setValue(anElPoint->x(), anElPoint->y());
+ aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
+ aPointFeature->execute();
+
+ std::string aName = theEllipse->name() + "_" + theCoincident;
+ aPointFeature->data()->setName(aName);
+ aPointFeature->lastResult()->data()->setName(aName);
+
+ if (theAuxOrName == AUXILIARY_VALUE)
+ aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+ else if (!theAuxOrName.empty()) {
+ aPointFeature->data()->setName(theAuxOrName);
+ aPointFeature->lastResult()->data()->setName(theAuxOrName);
+ }
+
+ createInternalConstraint(theSketch, anElPoint, aCoord);
+
+ theEntities.push_back(aPointFeature);
+}
+
+static void createAxis(const CompositeFeaturePtr& theSketch,
+ const FeaturePtr& theEllipse,
+ const std::string& theCoincidentStart,
+ const std::string& theCoincidentEnd,
+ const std::string& theAuxOrName,
+ std::list<FeaturePtr>& theEntities)
+{
+ if (theAuxOrName.empty())
+ return;
+
+ AttributePoint2DPtr aStartPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentStart));
+ AttributePoint2DPtr aEndPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEllipse->attribute(theCoincidentEnd));
+
+ FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID());
+ AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::START_ID()));
+ aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
+ AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::END_ID()));
+ aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
+ aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipse);
+ aLineFeature->execute();
+
+ std::string aName = theEllipse->name() + "_" +
+ (theCoincidentStart == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ?
+ "major_axis" : "minor_axis");
+ aLineFeature->data()->setName(aName);
+ aLineFeature->lastResult()->data()->setName(aName);
+
+ if (theAuxOrName == AUXILIARY_VALUE)
+ aLineFeature->boolean(SketchPlugin_Line::AUXILIARY_ID())->setValue(true);
+ else if (!theAuxOrName.empty()) {
+ aLineFeature->data()->setName(theAuxOrName);
+ aLineFeature->lastResult()->data()->setName(theAuxOrName);
+ }
+
+ createInternalConstraint(theSketch, aStartPoint, aLineStart);
+ createInternalConstraint(theSketch, aEndPoint, aLineEnd);
+
+ theEntities.push_back(aLineFeature);
+}
+
+std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::construction(
+ const std::string& center,
+ const std::string& firstFocus,
+ const std::string& secondFocus,
+ const std::string& majorAxisStart,
+ const std::string& majorAxisEnd,
+ const std::string& minorAxisStart,
+ const std::string& minorAxisEnd,
+ const std::string& majorAxis,
+ const std::string& minorAxis) const
+{
+ FeaturePtr anEllipse = feature();
+
+ std::list<PairOfStrings> anAttributes = ellipseAttrAndDumpNames();
+ // append start and end attributes for axes
+ anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
+ SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
+ anAttributes.push_back(PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
+ SketchPlugin_Ellipse::MINOR_AXIS_END_ID()));
+
+ return buildConstructionEntities(anEllipse, anAttributes, center, firstFocus, secondFocus,
+ majorAxisStart, majorAxisEnd, minorAxisStart, minorAxisEnd, majorAxis, minorAxis);
+}
+
+std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_Ellipse::buildConstructionEntities(
+ const FeaturePtr& theEllipse,
+ const std::list<PairOfStrings>& theAttributes,
+ const std::string& theCenter,
+ const std::string& theFirstFocus,
+ const std::string& theSecondFocus,
+ const std::string& theMajorAxisStart,
+ const std::string& theMajorAxisEnd,
+ const std::string& theMinorAxisStart,
+ const std::string& theMinorAxisEnd,
+ const std::string& theMajorAxis,
+ const std::string& theMinorAxis)
+{
+ CompositeFeaturePtr aSketch = sketchForFeature(theEllipse);
+
+ std::list<FeaturePtr> anEntities;
+ std::list<PairOfStrings>::const_iterator anAttrIt = theAttributes.begin();
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theCenter, anEntities);
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theFirstFocus, anEntities);
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theSecondFocus, anEntities);
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisStart, anEntities);
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMajorAxisEnd, anEntities);
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisStart, anEntities);
+ createPoint(aSketch, theEllipse, (anAttrIt++)->first, theMinorAxisEnd, anEntities);
+
+ createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMajorAxis, anEntities);
+ ++anAttrIt;
+ createAxis(aSketch, theEllipse, anAttrIt->first, anAttrIt->second, theMinorAxis, anEntities);
+
+ return SketchAPI_SketchEntity::wrap(anEntities);
+}
+
+static void ellipseAttributeAndAuxiliaryFeature(
+ const FeaturePtr& theInternalConstraint,
+ const std::pair<std::string, std::string>& theMajorAxisStartEnd,
+ const std::pair<std::string, std::string>& theMinorAxisStartEnd,
+ std::map<std::string, FeaturePtr>& theAttrToFeature)
+{
+ AttributeRefAttrPtr aRefAttrA =
+ theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr aRefAttrB =
+ theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+ // the first point is usually an ellipse attribute
+ // and the second point is an attribute of the auxiliary feature
+ ObjectPtr anAuxObject;
+ if (aRefAttrB->isObject())
+ anAuxObject = aRefAttrB->object();
+ else
+ anAuxObject = aRefAttrB->attr()->owner();
+
+ FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject);
+ if (anAuxFeature->getKind() == SketchPlugin_Point::ID())
+ theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature;
+ else {
+ const std::string& anAttrID = aRefAttrA->attr()->id();
+ if (anAttrID == theMajorAxisStartEnd.first || anAttrID == theMajorAxisStartEnd.second)
+ theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature;
+ else if (anAttrID == theMinorAxisStartEnd.first || anAttrID == theMinorAxisStartEnd.second)
+ theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature;
+ }
+}
+
+void SketchAPI_Ellipse::collectAuxiliaryFeatures(
+ FeaturePtr theEllipse,
+ const std::pair<std::string, std::string>& theMajorAxis,
+ const std::pair<std::string, std::string>& theMinorAxis,
+ std::map<std::string, FeaturePtr>& theAttrToFeature)
+{
+ const std::set<AttributePtr>& aRefs = theEllipse->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
+ aRefIt != aRefs.end(); ++aRefIt) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+ if (anOwner->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
+ // process internal constraints only
+ ellipseAttributeAndAuxiliaryFeature(anOwner, theMajorAxis, theMinorAxis, theAttrToFeature);
+ }
+ }
+}
+
+void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const
+{
+ if (isCopy())
+ return; // no need to dump copied feature
+
+ FeaturePtr aBase = feature();
+ const std::string& aSketchName = theDumper.parentName(aBase);
+
+ AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
+ if (anExternal->context()) {
+ // circle is external
+ theDumper << aBase << " = " << aSketchName << ".addEllipse(" << anExternal << ")" << std::endl;
+ } else {
+ // ellipse given by center, focus and radius
+ theDumper << aBase << " = " << aSketchName << ".addEllipse("
+ << center() << ", " << firstFocus() << ", " << minorRadius() << ")" << std::endl;
+ }
+ // dump "auxiliary" flag if necessary
+ SketchAPI_SketchEntity::dump(theDumper);
+
+ // dump auxiliary features produced by ellipse
+ std::map<std::string, FeaturePtr> anAuxFeatures;
+ static const std::pair<std::string, std::string> aMajorAxis(
+ SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
+ SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
+ static const std::pair<std::string, std::string> aMinorAxis(
+ SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
+ SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
+ collectAuxiliaryFeatures(aBase, aMajorAxis, aMinorAxis, anAuxFeatures);
+
+ if (!anAuxFeatures.empty()) {
+ // a list of attributes to write features in special order
+ const std::list<PairOfStrings>& anAttributes = ellipseAttrAndDumpNames();
+ dumpConstructionEntities(theDumper, aBase, anAttributes, anAuxFeatures);
+ }
+}
+
+void SketchAPI_Ellipse::dumpConstructionEntities(
+ ModelHighAPI_Dumper& theDumper,
+ const FeaturePtr& theEllipse,
+ const std::list<PairOfStrings>& theAttributes,
+ const std::map<std::string, FeaturePtr>& theAuxFeatures)
+{
+ std::list<PairOfStrings> anAttributes = theAttributes;
+ // append axes
+ anAttributes.push_back(PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID));
+ anAttributes.push_back(PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID));
+
+ theDumper << "[";
+ bool isFirst = true;
+ for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
+ anIt != anAttributes.end(); ++anIt) {
+ std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
+ if (aFound == theAuxFeatures.end())
+ continue;
+ if (!isFirst)
+ theDumper << ", ";
+ theDumper << theDumper.name(aFound->second, false);
+ theDumper.doNotDumpFeature(aFound->second);
+ isFirst = false;
+ }
+ theDumper << "] = " << theDumper.name(theEllipse) << ".construction(";
+ isFirst = true;
+ for (std::list<PairOfStrings>::iterator anIt = anAttributes.begin();
+ anIt != anAttributes.end(); ++anIt) {
+ std::map<std::string, FeaturePtr>::const_iterator aFound = theAuxFeatures.find(anIt->first);
+ if (aFound == theAuxFeatures.end())
+ continue;
+ if (!isFirst)
+ theDumper << ", ";
+ isFirst = false;
+ theDumper << anIt->second << " = \"";
+ if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value())
+ theDumper << AUXILIARY_VALUE;
+ else
+ theDumper << aFound->second->name();
+ theDumper << "\"";
+ }
+ theDumper << ")" << std::endl;
+}
--- /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 SketchAPI_Ellipse_H_
+#define SketchAPI_Ellipse_H_
+
+#include "SketchAPI.h"
+#include "SketchAPI_SketchEntity.h"
+
+#include <SketchPlugin_Ellipse.h>
+
+class ModelHighAPI_Selection;
+
+typedef std::pair<std::string, std::string> PairOfStrings;
+
+/// \class SketchAPI_Ellipse
+/// \ingroup CPPHighAPI
+/// \brief Interface for Ellipse feature.
+class SketchAPI_Ellipse : public SketchAPI_SketchEntity
+{
+public:
+ /// Constructor without values.
+ SKETCHAPI_EXPORT
+ explicit SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with values.
+ SKETCHAPI_EXPORT
+ SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theMinorRadius);
+
+ /// Constructor with values.
+ SKETCHAPI_EXPORT
+ SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ double theMinorRadius);
+
+ /// Constructor with external.
+ SKETCHAPI_EXPORT
+ SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theExternal);
+
+ /// Constructor with external.
+ SKETCHAPI_EXPORT
+ SketchAPI_Ellipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::string& theExternalName);
+
+ /// Destructor.
+ SKETCHAPI_EXPORT
+ virtual ~SketchAPI_Ellipse();
+
+ INTERFACE_10(SketchPlugin_Ellipse::ID(),
+ center, SketchPlugin_Ellipse::CENTER_ID(),
+ GeomDataAPI_Point2D, /** Center point */,
+ firstFocus, SketchPlugin_Ellipse::FIRST_FOCUS_ID(),
+ GeomDataAPI_Point2D, /** Focus in positive direction of a major axis */,
+ secondFocus, SketchPlugin_Ellipse::SECOND_FOCUS_ID(),
+ GeomDataAPI_Point2D, /** Focus in negative direction of a major axis */,
+ majorAxisNegative, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
+ GeomDataAPI_Point2D, /** Start point of major axis */,
+ majorAxisPositive, SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(),
+ GeomDataAPI_Point2D, /** End point of major axis */,
+ minorAxisNegative, SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
+ GeomDataAPI_Point2D, /** Start point of minor axis */,
+ minorAxisPositive, SketchPlugin_Ellipse::MINOR_AXIS_END_ID(),
+ GeomDataAPI_Point2D, /** End point of minor axis */,
+ majorRadius, SketchPlugin_Ellipse::MAJOR_RADIUS_ID(),
+ ModelAPI_AttributeDouble, /** Major radius */,
+ minorRadius, SketchPlugin_Ellipse::MINOR_RADIUS_ID(),
+ ModelAPI_AttributeDouble, /** Minor radius */,
+ external, SketchPlugin_Ellipse::EXTERNAL_ID(),
+ ModelAPI_AttributeSelection, /** External */)
+
+ /// Set by center, focus and radius.
+ SKETCHAPI_EXPORT
+ void setByCenterFocusAndRadius(double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theMinorRadius);
+
+ /// Set by center, focus and radius.
+ SKETCHAPI_EXPORT
+ void setByCenterFocusAndRadius(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ double theMinorRadius);
+
+ /// Set by external.
+ SKETCHAPI_EXPORT
+ void setByExternal(const ModelHighAPI_Selection& theExternal);
+
+ /// Set by external name.
+ SKETCHAPI_EXPORT
+ void setByExternalName(const std::string& theExternalName);
+
+ /// Set center.
+ SKETCHAPI_EXPORT
+ void setCenter(double theX, double theY);
+
+ /// Set center.
+ SKETCHAPI_EXPORT
+ void setCenter(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter);
+
+ /// Set focus.
+ SKETCHAPI_EXPORT
+ void setFocus(double theX, double theY);
+
+ /// Set focus.
+ SKETCHAPI_EXPORT
+ void setFocus(const std::shared_ptr<GeomAPI_Pnt2d>& theFocus);
+
+ /// Set radius.
+ SKETCHAPI_EXPORT
+ void setMinorRadius(double theRadius);
+
+ /// Create construction elements (focuses, axes etc.).
+ /// Empty value for each parameter shows that the corresponding feature has been removed.
+ /// Value "aux" marks this feature as auxiliary.
+ /// And the name of the feature shows that it is a regular feature.
+ SKETCHAPI_EXPORT
+ std::list<std::shared_ptr<SketchAPI_SketchEntity> > construction(
+ const std::string& center = std::string(),
+ const std::string& firstFocus = std::string(),
+ const std::string& secondFocus = std::string(),
+ const std::string& majorAxisStart = std::string(),
+ const std::string& majorAxisEnd = std::string(),
+ const std::string& minorAxisStart = std::string(),
+ const std::string& minorAxisEnd = std::string(),
+ const std::string& majorAxis = std::string(),
+ const std::string& minorAxis = std::string()) const;
+
+ /// Dump wrapped feature
+ SKETCHAPI_EXPORT
+ virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+
+private:
+ /// Find all features connected with theEllipse by the internal coincidence.
+ /// \param[in] theEllipse ellipse or elliptic arc
+ /// \param[in] theMajorAxis names of attributes composing a major axis of ellipse
+ /// \param[in] theMinorAxis names of attributes composing a minor axis of ellipse
+ /// \param[out] theAttrToFeature map attribute of ellipse and coincident auxiliary feature
+ static void collectAuxiliaryFeatures(FeaturePtr theEllipse,
+ const PairOfStrings& theMajorAxis,
+ const PairOfStrings& theMinorAxis,
+ std::map<std::string, FeaturePtr>& theAttrToFeature);
+
+ /// \brief Dump the construction features (points, axes) for the ellipse.
+ /// \param[in] theDumper dumper instance
+ /// \param[in] theAttributes list of attributes the construction points are
+ /// connected with, and their dump names
+ /// \param[in] theAuxFeatures list of construction features
+ static void dumpConstructionEntities(ModelHighAPI_Dumper& theDumper,
+ const FeaturePtr& theEllipse,
+ const std::list<PairOfStrings>& theAttributes,
+ const std::map<std::string, FeaturePtr>& theAuxFeatures);
+
+ /// \brief Create construction features for the ellipse connected
+ /// with corresponding attribute of ellipse.
+ static std::list<std::shared_ptr<SketchAPI_SketchEntity> > buildConstructionEntities(
+ const FeaturePtr& theEllipse,
+ const std::list<PairOfStrings>& theAttributes,
+ const std::string& theCenter,
+ const std::string& theFirstFocus,
+ const std::string& theSecondFocus,
+ const std::string& theMajorAxisStart,
+ const std::string& theMajorAxisEnd,
+ const std::string& theMinorAxisStart,
+ const std::string& theMinorAxisEnd,
+ const std::string& theMajorAxis,
+ const std::string& theMinorAxis);
+
+ friend class SketchAPI_EllipticArc;
+};
+
+/// Pointer on Ellipse object.
+typedef std::shared_ptr<SketchAPI_Ellipse> EllipsePtr;
+
+#endif // SketchPlugin_Ellipse_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 "SketchAPI_EllipticArc.h"
+#include "SketchAPI_Ellipse.h"
+
+#include <GeomAPI_Pnt2d.h>
+
+#include <ModelHighAPI_Dumper.h>
+#include <ModelHighAPI_Selection.h>
+#include <ModelHighAPI_Tools.h>
+
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+
+SketchAPI_EllipticArc::SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature> & theFeature)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ initialize();
+}
+
+SketchAPI_EllipticArc::SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theStartX, double theStartY,
+ double theEndX, double theEndY,
+ bool theInversed)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if(initialize()) {
+ setByCenterFocusAndPoints(theCenterX, theCenterY, theFocusX, theFocusY,
+ theStartX, theStartY, theEndX, theEndY, theInversed);
+ }
+}
+
+SketchAPI_EllipticArc::SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
+ bool theInversed)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if(initialize()) {
+ setByCenterFocusAndPoints(theCenter, theFocus, theStart, theEnd, theInversed);
+ }
+}
+
+SketchAPI_EllipticArc::SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theExternal)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ setByExternal(theExternal);
+ }
+}
+
+SketchAPI_EllipticArc::SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::string& theExternalName)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ setByExternalName(theExternalName);
+ }
+}
+
+SketchAPI_EllipticArc::~SketchAPI_EllipticArc()
+{
+}
+
+void SketchAPI_EllipticArc::setByCenterFocusAndPoints(double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theStartX, double theStartY,
+ double theEndX, double theEndY,
+ bool theInversed)
+{
+ // the order of attribute initialization is reversed to avoid odd recalculation of an elliptic arc
+ fillAttribute(theInversed, reversed());
+ fillAttribute(endPoint(), theEndX, theEndY);
+ fillAttribute(startPoint(), theStartX, theStartY);
+ fillAttribute(firstFocus(), theFocusX, theFocusY);
+ fillAttribute(center(), theCenterX, theCenterY);
+
+ execute();
+}
+
+void SketchAPI_EllipticArc::setByCenterFocusAndPoints(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
+ bool theInversed)
+{
+ // the order of attribute initialization is reversed to avoid odd recalculation of an elliptic arc
+ fillAttribute(theInversed, reversed());
+ fillAttribute(theEnd, endPoint());
+ fillAttribute(theStart, startPoint());
+ fillAttribute(theFocus, firstFocus());
+ fillAttribute(theCenter, center());
+
+ execute();
+}
+
+void SketchAPI_EllipticArc::setByExternal(const ModelHighAPI_Selection & theExternal)
+{
+ fillAttribute(theExternal, external());
+ execute();
+}
+
+void SketchAPI_EllipticArc::setByExternalName(const std::string & theExternalName)
+{
+ fillAttribute(ModelHighAPI_Selection("EDGE", theExternalName), external());
+ execute();
+}
+
+void SketchAPI_EllipticArc::setCenter(double theX, double theY)
+{
+ fillAttribute(center(), theX, theY);
+ execute();
+}
+
+void SketchAPI_EllipticArc::setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter)
+{
+ fillAttribute(theCenter, mycenter);
+ execute();
+}
+
+void SketchAPI_EllipticArc::setFocus(double theX, double theY)
+{
+ fillAttribute(firstFocus(), theX, theY);
+ execute();
+}
+
+void SketchAPI_EllipticArc::setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus)
+{
+ fillAttribute(theFocus, myfirstFocus);
+ execute();
+}
+
+static const std::list<PairOfStrings>& ellipticArcAttrAndDumpNames()
+{
+ static std::list<PairOfStrings> anAttributes;
+ if (anAttributes.empty()) {
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::CENTER_ID(), "center"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::FIRST_FOCUS_ID(), "firstFocus"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::SECOND_FOCUS_ID(), "secondFocus"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID(), "majorAxisStart"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID(), "majorAxisEnd"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID(), "minorAxisStart"));
+ anAttributes.push_back(
+ PairOfStrings(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID(), "minorAxisEnd"));
+ }
+ return anAttributes;
+}
+
+std::list<std::shared_ptr<SketchAPI_SketchEntity> > SketchAPI_EllipticArc::construction(
+ const std::string& center,
+ const std::string& firstFocus,
+ const std::string& secondFocus,
+ const std::string& majorAxisStart,
+ const std::string& majorAxisEnd,
+ const std::string& minorAxisStart,
+ const std::string& minorAxisEnd,
+ const std::string& majorAxis,
+ const std::string& minorAxis) const
+{
+ FeaturePtr anEllipse = feature();
+
+ std::list<PairOfStrings> anAttributes = ellipticArcAttrAndDumpNames();
+ // append start and end attributes for axes
+ anAttributes.push_back(PairOfStrings(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID()));
+ anAttributes.push_back(PairOfStrings(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MINOR_AXIS_END_ID()));
+
+ return SketchAPI_Ellipse::buildConstructionEntities(anEllipse, anAttributes,
+ center, firstFocus, secondFocus,
+ majorAxisStart, majorAxisEnd,
+ minorAxisStart, minorAxisEnd,
+ majorAxis, minorAxis);
+}
+
+void SketchAPI_EllipticArc::dump(ModelHighAPI_Dumper& theDumper) const
+{
+ if (isCopy())
+ return; // no need to dump copied feature
+
+ FeaturePtr aBase = feature();
+ const std::string& aSketchName = theDumper.parentName(aBase);
+
+ AttributeSelectionPtr anExternal = aBase->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
+ if (anExternal->context()) {
+ // circle is external
+ theDumper << aBase << " = " << aSketchName << ".addEllipticArc("
+ << anExternal << ")" << std::endl;
+ } else {
+ // ellipse given by center, focus and radius
+ theDumper << aBase << " = " << aSketchName << ".addEllipticArc("
+ << center() << ", " << firstFocus() << ", "
+ << startPoint() << ", " << endPoint() << ", "
+ << reversed() << ")" << std::endl;
+ }
+ // dump "auxiliary" flag if necessary
+ SketchAPI_SketchEntity::dump(theDumper);
+
+ // dump auxiliary features produced by elliptic arc
+ std::map<std::string, FeaturePtr> anAuxFeatures;
+ static const std::pair<std::string, std::string> aMajorAxis(
+ SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID());
+ static const std::pair<std::string, std::string> aMinorAxis(
+ SketchPlugin_EllipticArc::MINOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MINOR_AXIS_END_ID());
+ SketchAPI_Ellipse::collectAuxiliaryFeatures(aBase, aMajorAxis, aMinorAxis, anAuxFeatures);
+
+ if (!anAuxFeatures.empty()) {
+ // a list of attributes to write features in special order
+ static std::list<PairOfStrings> anAttributes = ellipticArcAttrAndDumpNames();
+ SketchAPI_Ellipse::dumpConstructionEntities(theDumper, aBase, anAttributes, anAuxFeatures);
+ }
+}
--- /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 SketchAPI_EllipticArc_H_
+#define SketchAPI_EllipticArc_H_
+
+#include "SketchAPI.h"
+#include "SketchAPI_SketchEntity.h"
+
+#include <SketchPlugin_EllipticArc.h>
+
+class ModelHighAPI_Selection;
+
+/// \class SketchAPI_EllipticArc
+/// \ingroup CPPHighAPI
+/// \brief Interface for Elliptic Arc feature.
+class SketchAPI_EllipticArc : public SketchAPI_SketchEntity
+{
+public:
+ /// Constructor without values.
+ SKETCHAPI_EXPORT
+ explicit SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with values.
+ SKETCHAPI_EXPORT
+ SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theStartX, double theStartY,
+ double theEndX, double theEndY,
+ bool theInversed);
+
+ /// Constructor with values.
+ SKETCHAPI_EXPORT
+ SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
+ bool theInversed);
+
+ /// Constructor with external.
+ SKETCHAPI_EXPORT
+ SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const ModelHighAPI_Selection& theExternal);
+
+ /// Constructor with external.
+ SKETCHAPI_EXPORT
+ SketchAPI_EllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::string& theExternalName);
+
+ /// Destructor.
+ SKETCHAPI_EXPORT
+ virtual ~SketchAPI_EllipticArc();
+
+ INTERFACE_13(SketchPlugin_EllipticArc::ID(),
+ center, SketchPlugin_EllipticArc::CENTER_ID(),
+ GeomDataAPI_Point2D, /** Center point */,
+ startPoint, SketchPlugin_EllipticArc::START_POINT_ID(),
+ GeomDataAPI_Point2D, /** Start point of elliptic arc */,
+ endPoint, SketchPlugin_EllipticArc::END_POINT_ID(),
+ GeomDataAPI_Point2D, /** End point of elliptic arc */,
+ reversed, SketchPlugin_EllipticArc::REVERSED_ID(),
+ ModelAPI_AttributeBoolean, /** Inversed flag */,
+ firstFocus, SketchPlugin_EllipticArc::FIRST_FOCUS_ID(),
+ GeomDataAPI_Point2D, /** Focus in positive direction of a major axis */,
+ secondFocus, SketchPlugin_EllipticArc::SECOND_FOCUS_ID(),
+ GeomDataAPI_Point2D, /** Focus in negative direction of a major axis */,
+ majorAxisNegative, SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID(),
+ GeomDataAPI_Point2D, /** Start point of major axis */,
+ majorAxisPositive, SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID(),
+ GeomDataAPI_Point2D, /** End point of major axis */,
+ minorAxisNegative, SketchPlugin_EllipticArc::MINOR_AXIS_START_ID(),
+ GeomDataAPI_Point2D, /** Start point of minor axis */,
+ minorAxisPositive, SketchPlugin_EllipticArc::MINOR_AXIS_END_ID(),
+ GeomDataAPI_Point2D, /** End point of minor axis */,
+ majorRadius, SketchPlugin_EllipticArc::MAJOR_RADIUS_ID(),
+ ModelAPI_AttributeDouble, /** Major radius */,
+ minorRadius, SketchPlugin_EllipticArc::MINOR_RADIUS_ID(),
+ ModelAPI_AttributeDouble, /** Minor radius */,
+ external, SketchPlugin_EllipticArc::EXTERNAL_ID(),
+ ModelAPI_AttributeSelection, /** External */)
+
+ /// Set by center, focus and radius.
+ SKETCHAPI_EXPORT
+ void setByCenterFocusAndPoints(double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theStartX, double theStartY,
+ double theEndX, double theEndY,
+ bool theInversed);
+
+ /// Set by center, focus and radius.
+ SKETCHAPI_EXPORT
+ void setByCenterFocusAndPoints(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStart,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
+ bool theInversed);
+
+ /// Set by external.
+ SKETCHAPI_EXPORT
+ void setByExternal(const ModelHighAPI_Selection& theExternal);
+
+ /// Set by external name.
+ SKETCHAPI_EXPORT
+ void setByExternalName(const std::string& theExternalName);
+
+ /// Set center.
+ SKETCHAPI_EXPORT
+ void setCenter(double theX, double theY);
+
+ /// Set center.
+ SKETCHAPI_EXPORT
+ void setCenter(const std::shared_ptr<GeomAPI_Pnt2d> & theCenter);
+
+ /// Set focus.
+ SKETCHAPI_EXPORT
+ void setFocus(double theX, double theY);
+
+ /// Set focus.
+ SKETCHAPI_EXPORT
+ void setFocus(const std::shared_ptr<GeomAPI_Pnt2d> & theFocus);
+
+ /// Create construction elements (focuses, axes etc.).
+ /// Empty value for each parameter shows that the corresponding feature has been removed.
+ /// Value "aux" marks this feature as auxiliary.
+ /// And the name of the feature shows that it is a regular feature.
+ SKETCHAPI_EXPORT
+ std::list<std::shared_ptr<SketchAPI_SketchEntity> > construction(
+ const std::string& center = std::string(),
+ const std::string& firstFocus = std::string(),
+ const std::string& secondFocus = std::string(),
+ const std::string& majorAxisStart = std::string(),
+ const std::string& majorAxisEnd = std::string(),
+ const std::string& minorAxisStart = std::string(),
+ const std::string& minorAxisEnd = std::string(),
+ const std::string& majorAxis = std::string(),
+ const std::string& minorAxis = std::string()) const;
+
+ /// Dump wrapped feature
+ SKETCHAPI_EXPORT
+ virtual void dump(ModelHighAPI_Dumper& theDumper) const;
+};
+
+/// Pointer on Ellipse object.
+typedef std::shared_ptr<SketchAPI_EllipticArc> EllipticArcPtr;
+
+#endif // SketchAPI_EllipticArc_H_
execute();
}
+
+//================================================================================================
+void SketchAPI_MacroArc::setByTransversal(const ModelHighAPI_RefAttr& theTransversalPoint,
+ double theEndX, double theEndY,
+ bool theInversed)
+{
+ fillAttribute(SketchPlugin_MacroArc::ARC_TYPE_BY_TRANSVERSAL_LINE(), myarcType);
+ fillAttribute(theTransversalPoint, mytangentPoint);
+ fillAttribute(endPoint3(), theEndX, theEndY);
+ fillAttribute(theInversed, myreversed);
+
+ execute();
+}
+
+//================================================================================================
+void SketchAPI_MacroArc::setByTransversal(const ModelHighAPI_RefAttr& theTransversalPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
+ bool theInversed)
+{
+ fillAttribute(SketchPlugin_MacroArc::ARC_TYPE_BY_TRANSVERSAL_LINE(), myarcType);
+ fillAttribute(theTransversalPoint, mytangentPoint);
+ fillAttribute(theEnd, myendPoint3);
+ fillAttribute(theInversed, myreversed);
+
+ execute();
+}
angle, SketchPlugin_MacroArc::ANGLE_ID(),
ModelAPI_AttributeDouble, /** Angle */)
-private:
-
/// Set by center and start, end point.
SKETCHAPI_EXPORT
void setByCenterStartEnd(double theCenterX, double theCenterY,
void setByTangent(const ModelHighAPI_RefAttr& theTangentPoint,
const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
bool theInversed);
+
+ /// Set by tangent and end point.
+ SKETCHAPI_EXPORT
+ void setByTransversal(const ModelHighAPI_RefAttr& theTransversalPoint,
+ double theEndX, double theEndY,
+ bool theInversed);
+
+ /// Set by tangent and end point.
+ SKETCHAPI_EXPORT
+ void setByTransversal(const ModelHighAPI_RefAttr& theTransversalPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
+ bool theInversed);
};
/// Pointer on Arc 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 "SketchAPI_MacroEllipse.h"
+#include "SketchAPI_Line.h"
+#include "SketchAPI_Point.h"
+
+#include <GeomAPI_Pnt2d.h>
+
+#include <ModelHighAPI_RefAttr.h>
+#include <ModelHighAPI_Tools.h>
+
+#include <SketchPlugin_Sketch.h>
+
+#define POINT_ATTR(x) (std::dynamic_pointer_cast<GeomDataAPI_Point2D>(feature()->attribute((x))))
+#define POINT_REF(x) (feature()->refattr((x)))
+
+
+SketchAPI_MacroEllipse::SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ bool callInitialize)
+: SketchAPI_SketchEntity(theFeature)
+{
+ if (callInitialize && initialize())
+ storeSketch(theFeature);
+}
+
+SketchAPI_MacroEllipse::SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ double theX1, double theY1,
+ double theX2, double theY2,
+ double theX3, double theY3,
+ bool byCenter)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ static const ModelHighAPI_RefAttr DUMMY_REF;
+
+ GeomPnt2dPtr aPnt1(new GeomAPI_Pnt2d(theX1, theY1));
+ GeomPnt2dPtr aPnt2(new GeomAPI_Pnt2d(theX2, theY2));
+ GeomPnt2dPtr aPnt3(new GeomAPI_Pnt2d(theX3, theY3));
+
+ if (byCenter)
+ setByCenterAndPassedPoints(aPnt1, DUMMY_REF, aPnt2, DUMMY_REF, aPnt3, DUMMY_REF);
+ else
+ setByMajorAxisAndPassedPoint(aPnt1, DUMMY_REF, aPnt2, DUMMY_REF, aPnt3, DUMMY_REF);
+ }
+}
+
+SketchAPI_MacroEllipse::SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+ bool byCenter)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ static const ModelHighAPI_RefAttr DUMMY_REF;
+ if (byCenter)
+ setByCenterAndPassedPoints(thePoint1, DUMMY_REF, thePoint2, DUMMY_REF, thePoint3, DUMMY_REF);
+ else {
+ setByMajorAxisAndPassedPoint(thePoint1, DUMMY_REF,
+ thePoint2, DUMMY_REF,
+ thePoint3, DUMMY_REF);
+ }
+ }
+}
+
+SketchAPI_MacroEllipse::SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+ const ModelHighAPI_RefAttr& thePoint1Ref,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+ const ModelHighAPI_RefAttr& thePoint2Ref,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+ const ModelHighAPI_RefAttr& thePoint3Ref,
+ bool byCenter)
+ : SketchAPI_SketchEntity(theFeature)
+{
+ if (initialize()) {
+ if (byCenter) {
+ setByCenterAndPassedPoints(thePoint1, thePoint1Ref,
+ thePoint2, thePoint2Ref,
+ thePoint3, thePoint3Ref);
+ }
+ else {
+ setByMajorAxisAndPassedPoint(thePoint1, thePoint1Ref,
+ thePoint2, thePoint2Ref,
+ thePoint3, thePoint3Ref);
+ }
+ }
+}
+
+SketchAPI_MacroEllipse::~SketchAPI_MacroEllipse()
+{
+}
+
+static void fillAttribute(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint,
+ const ModelHighAPI_RefAttr& thePointRef,
+ std::shared_ptr<GeomDataAPI_Point2D> thePointAttr,
+ AttributeRefAttrPtr thePointRefAttr)
+{
+ GeomPnt2dPtr aPoint = thePoint;
+ if (!thePointRef.isEmpty()) {
+ fillAttribute(thePointRef, thePointRefAttr);
+ std::shared_ptr<GeomDataAPI_Point2D> anAttrPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePointRefAttr->attr());
+ if (anAttrPnt)
+ aPoint = anAttrPnt->pnt();
+ }
+ fillAttribute(aPoint, thePointAttr);
+}
+
+void SketchAPI_MacroEllipse::setByCenterAndPassedPoints(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const ModelHighAPI_RefAttr& theCenterRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisPoint,
+ const ModelHighAPI_RefAttr& theMajorAxisPointRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+ const ModelHighAPI_RefAttr& thePassedPointRef)
+{
+ fillAttribute(SketchPlugin_MacroEllipse::ELLIPSE_TYPE_BY_CENTER_AXIS_POINT(), myellipseType);
+
+ AttributePoint2DPtr aCenterAttr = POINT_ATTR(SketchPlugin_MacroEllipse::CENTER_POINT_ID());
+ AttributePoint2DPtr aMajorAxisAttr = POINT_ATTR(SketchPlugin_MacroEllipse::MAJOR_AXIS_POINT_ID());
+ AttributePoint2DPtr aPassedAttr = POINT_ATTR(SketchPlugin_MacroEllipse::PASSED_POINT_ID());
+
+ AttributeRefAttrPtr aCenterRef = POINT_REF(SketchPlugin_MacroEllipse::CENTER_POINT_REF_ID());
+ AttributeRefAttrPtr aMajorAxisRef =
+ POINT_REF(SketchPlugin_MacroEllipse::MAJOR_AXIS_POINT_REF_ID());
+ AttributeRefAttrPtr aPassedRef = POINT_REF(SketchPlugin_MacroEllipse::PASSED_POINT_REF_ID());
+
+ fillAttribute(theCenter, theCenterRef, aCenterAttr, aCenterRef);
+ fillAttribute(theMajorAxisPoint, theMajorAxisPointRef, aMajorAxisAttr, aMajorAxisRef);
+ fillAttribute(thePassedPoint, thePassedPointRef, aPassedAttr, aPassedRef);
+
+ storeSketch(feature());
+ execute();
+}
+
+void SketchAPI_MacroEllipse::setByMajorAxisAndPassedPoint(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisStart,
+ const ModelHighAPI_RefAttr& theMajorAxisStartRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisEnd,
+ const ModelHighAPI_RefAttr& theMajorAxisEndRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+ const ModelHighAPI_RefAttr& thePassedPointRef)
+{
+ fillAttribute(SketchPlugin_MacroEllipse::ELLIPSE_TYPE_BY_AXIS_AND_POINT(), myellipseType);
+
+ AttributePoint2DPtr aMajorAxisStartAttr =
+ POINT_ATTR(SketchPlugin_MacroEllipse::MAJOR_AXIS_START_ID());
+ AttributePoint2DPtr aMajorAxisEndAttr =
+ POINT_ATTR(SketchPlugin_MacroEllipse::MAJOR_AXIS_END_ID());
+ AttributePoint2DPtr aPassedAttr = POINT_ATTR(SketchPlugin_MacroEllipse::PASSED_POINT_1_ID());
+
+ AttributeRefAttrPtr aMajorAxisStartRef =
+ POINT_REF(SketchPlugin_MacroEllipse::MAJOR_AXIS_START_REF_ID());
+ AttributeRefAttrPtr aMajorAxisEndRef =
+ POINT_REF(SketchPlugin_MacroEllipse::MAJOR_AXIS_END_REF_ID());
+ AttributeRefAttrPtr aPassedRef = POINT_REF(SketchPlugin_MacroEllipse::PASSED_POINT_1_REF_ID());
+
+ fillAttribute(theMajorAxisStart, theMajorAxisStartRef, aMajorAxisStartAttr, aMajorAxisStartRef);
+ fillAttribute(theMajorAxisEnd, theMajorAxisEndRef, aMajorAxisEndAttr, aMajorAxisEndRef);
+ fillAttribute(thePassedPoint, thePassedPointRef, aPassedAttr, aPassedRef);
+
+ storeSketch(feature());
+ execute();
+}
+
+void SketchAPI_MacroEllipse::storeSketch(const FeaturePtr& theFeature)
+{
+ const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt)
+ if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID()) {
+ mySketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>((*anIt)->owner());
+ break;
+ }
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::center()
+{
+ if (!myCenter)
+ collectAuxiliary();
+ return myCenter;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::focus1()
+{
+ if (!myFocus1)
+ collectAuxiliary();
+ return myFocus1;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::focus2()
+{
+ if (!myFocus2)
+ collectAuxiliary();
+ return myFocus2;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::majorAxisStart()
+{
+ if (!myMajorAxisStart)
+ collectAuxiliary();
+ return myMajorAxisStart;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::majorAxisEnd()
+{
+ if (!myMajorAxisEnd)
+ collectAuxiliary();
+ return myMajorAxisEnd;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::minorAxisStart()
+{
+ if (!myMinorAxisStart)
+ collectAuxiliary();
+ return myMinorAxisStart;
+}
+
+std::shared_ptr<SketchAPI_Point> SketchAPI_MacroEllipse::minorAxisEnd()
+{
+ if (!myMinorAxisEnd)
+ collectAuxiliary();
+ return myMinorAxisEnd;
+}
+
+std::shared_ptr<SketchAPI_Line> SketchAPI_MacroEllipse::majorAxis()
+{
+ if (!myMajorAxis)
+ collectAuxiliary();
+ return myMajorAxis;
+}
+
+std::shared_ptr<SketchAPI_Line> SketchAPI_MacroEllipse::minorAxis()
+{
+ if (!myMinorAxis)
+ collectAuxiliary();
+ return myMinorAxis;
+}
+
+void SketchAPI_MacroEllipse::collectAuxiliary()
+{
+ // collect auxiliary features
+ int aNbSubs = mySketch->numberOfSubs();
+ std::shared_ptr<SketchAPI_Point>* anAuxPoint[] = {
+ &myCenter, &myFocus1, &myFocus2,
+ &myMajorAxisStart, &myMajorAxisEnd,
+ &myMinorAxisStart, &myMinorAxisEnd
+ };
+ std::shared_ptr<SketchAPI_Line>* anAuxLine[] = {&myMajorAxis, &myMinorAxis};
+ for (int aPtInd = 7, aLinInd = 2; (aPtInd > 0 || aLinInd > 0) && aNbSubs >= 0; ) {
+ FeaturePtr aCurFeature = mySketch->subFeature(--aNbSubs);
+ if (aPtInd > 0 && aCurFeature->getKind() == SketchPlugin_Point::ID())
+ anAuxPoint[--aPtInd]->reset(new SketchAPI_Point(aCurFeature));
+ else if (aLinInd > 0 && aCurFeature->getKind() == SketchPlugin_Line::ID())
+ anAuxLine[--aLinInd]->reset(new SketchAPI_Line(aCurFeature));
+ }
+}
--- /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 SketchAPI_MacroEllipse_H_
+#define SketchAPI_MacroEllipse_H_
+
+#include "SketchAPI.h"
+#include "SketchAPI_SketchEntity.h"
+
+#include <SketchPlugin_MacroEllipse.h>
+
+class ModelHighAPI_RefAttr;
+class SketchAPI_Point;
+class SketchAPI_Line;
+
+/// \class SketchAPI_MacroEllipse
+/// \ingroup CPPHighAPI
+/// \brief Interface for Ellipse feature.
+class SketchAPI_MacroEllipse: public SketchAPI_SketchEntity
+{
+public:
+ /// Constructor without values.
+ SKETCHAPI_EXPORT
+ explicit SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ bool callInitialize = true);
+
+ /// Constructor with values.
+ SKETCHAPI_EXPORT
+ SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ double theX1, double theY1,
+ double theX2, double theY2,
+ double theX3, double theY3,
+ bool byCenter = true);
+
+ /// Constructor with values.
+ SKETCHAPI_EXPORT
+ SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+ bool byCenter = true);
+
+ /// Constructor with values and/or references.
+ SKETCHAPI_EXPORT
+ SketchAPI_MacroEllipse(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint1,
+ const ModelHighAPI_RefAttr& thePoint1Ref,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint2,
+ const ModelHighAPI_RefAttr& thePoint2Ref,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePoint3,
+ const ModelHighAPI_RefAttr& thePoint3Ref,
+ bool byCenter = true);
+
+ /// Destructor.
+ SKETCHAPI_EXPORT
+ virtual ~SketchAPI_MacroEllipse();
+
+ INTERFACE_1(SketchPlugin_MacroEllipse::ID(),
+ ellipseType, SketchPlugin_MacroEllipse::ELLIPSE_TYPE(),
+ ModelAPI_AttributeString, /** Ellipse type */)
+
+ /// Return created auxiliary center point
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> center();
+ /// Return created auxiliary focus in the positive direction of major axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> focus1();
+ /// Return created auxiliary focus in the negative direction of major axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> focus2();
+ /// Return created auxiliary point - start of major axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> majorAxisStart();
+ /// Return created auxiliary point - end of major axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> majorAxisEnd();
+ /// Return created auxiliary point - start of minor axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> minorAxisStart();
+ /// Return created auxiliary point - end of minor axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Point> minorAxisEnd();
+ /// Return created auxiliary major axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Line> majorAxis();
+ /// Return created auxiliary minor axis
+ SKETCHAPI_EXPORT std::shared_ptr<SketchAPI_Line> minorAxis();
+
+protected:
+ // find a parent sketch
+ void storeSketch(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+private:
+ /// Set flag of creation by center, major semi-axis and passed point.
+ void setByCenterAndPassedPoints(const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const ModelHighAPI_RefAttr& theCenterRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisPoint,
+ const ModelHighAPI_RefAttr& theMajorAxisPointRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+ const ModelHighAPI_RefAttr& thePassedPointRef);
+ /// Set flag of creation by major axis and passed point.
+ void setByMajorAxisAndPassedPoint(const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisStart,
+ const ModelHighAPI_RefAttr& theMajorAxisStartRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisEnd,
+ const ModelHighAPI_RefAttr& theMajorAxisEndRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& thePassedPoint,
+ const ModelHighAPI_RefAttr& thePassedPointRef);
+
+ /// Collect auxiliary features
+ void collectAuxiliary();
+
+private:
+ CompositeFeaturePtr mySketch;
+ std::shared_ptr<SketchAPI_Point> myCenter;
+ std::shared_ptr<SketchAPI_Point> myFocus1;
+ std::shared_ptr<SketchAPI_Point> myFocus2;
+ std::shared_ptr<SketchAPI_Point> myMajorAxisStart;
+ std::shared_ptr<SketchAPI_Point> myMajorAxisEnd;
+ std::shared_ptr<SketchAPI_Point> myMinorAxisStart;
+ std::shared_ptr<SketchAPI_Point> myMinorAxisEnd;
+ std::shared_ptr<SketchAPI_Line> myMajorAxis;
+ std::shared_ptr<SketchAPI_Line> myMinorAxis;
+};
+
+/// Pointer on Circle object.
+typedef std::shared_ptr<SketchAPI_MacroEllipse> MacroEllipsePtr;
+
+#endif // SketchAPI_MacroEllipse_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 "SketchAPI_MacroEllipticArc.h"
+
+#include <GeomAPI_Pnt2d.h>
+
+#include <ModelHighAPI_RefAttr.h>
+#include <ModelHighAPI_Tools.h>
+
+#include <SketchPlugin_MacroEllipticArc.h>
+
+#define CENTER_POINT (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+ feature()->attribute(SketchPlugin_MacroEllipticArc::CENTER_ID())))
+#define MAJOR_AXIS_POSITIVE (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+ feature()->attribute(SketchPlugin_MacroEllipticArc::MAJOR_AXIS_POINT_ID())))
+#define START_POINT (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+ feature()->attribute(SketchPlugin_MacroEllipticArc::START_POINT_ID())))
+#define END_POINT (std::dynamic_pointer_cast<GeomDataAPI_Point2D>( \
+ feature()->attribute(SketchPlugin_MacroEllipticArc::END_POINT_ID())))
+
+#define CENTER_POINT_REF (feature()->refattr(SketchPlugin_MacroEllipticArc::CENTER_REF_ID()))
+#define MAJOR_AXIS_POSITIVE_REF (feature()->refattr( \
+ SketchPlugin_MacroEllipticArc::MAJOR_AXIS_POINT_REF_ID()))
+#define START_POINT_REF (feature()->refattr(SketchPlugin_MacroEllipticArc::START_POINT_REF_ID()))
+#define END_POINT_REF (feature()->refattr(SketchPlugin_MacroEllipticArc::END_POINT_REF_ID()))
+
+
+static void fillAttribute(const std::shared_ptr<GeomAPI_Pnt2d>& thePoint,
+ const ModelHighAPI_RefAttr& thePointRef,
+ std::shared_ptr<GeomDataAPI_Point2D> thePointAttr,
+ AttributeRefAttrPtr thePointRefAttr)
+{
+ GeomPnt2dPtr aPoint = thePoint;
+ if (!thePointRef.isEmpty()) {
+ fillAttribute(thePointRef, thePointRefAttr);
+ std::shared_ptr<GeomDataAPI_Point2D> anAttrPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePointRefAttr->attr());
+ if (anAttrPnt)
+ aPoint = anAttrPnt->pnt();
+ }
+ fillAttribute(aPoint, thePointAttr);
+}
+
+SketchAPI_MacroEllipticArc::SketchAPI_MacroEllipticArc(const FeaturePtr& theFeature)
+ : SketchAPI_MacroEllipse(theFeature, false)
+{
+}
+
+SketchAPI_MacroEllipticArc::SketchAPI_MacroEllipticArc(
+ const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const ModelHighAPI_RefAttr& theCenterRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisPoint,
+ const ModelHighAPI_RefAttr& theMajorAxisPointRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theArcStart,
+ const ModelHighAPI_RefAttr& theArcStartRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theArcEnd,
+ const ModelHighAPI_RefAttr& theArcEndRef,
+ const bool theReversed)
+ : SketchAPI_MacroEllipse(theFeature, false)
+{
+ if (initialize()) {
+ fillAttribute(theCenter, theCenterRef,
+ CENTER_POINT, CENTER_POINT_REF);
+ fillAttribute(theMajorAxisPoint, theMajorAxisPointRef,
+ MAJOR_AXIS_POSITIVE, MAJOR_AXIS_POSITIVE_REF);
+ fillAttribute(theArcStart, theArcStartRef, START_POINT, START_POINT_REF);
+ fillAttribute(theArcEnd, theArcEndRef, END_POINT, END_POINT_REF);
+
+ fillAttribute(theReversed, reversed());
+
+ storeSketch(theFeature);
+ execute();
+ }
+}
+
+SketchAPI_MacroEllipticArc::~SketchAPI_MacroEllipticArc()
+{
+}
--- /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 SketchAPI_MacroEllipticArc_H_
+#define SketchAPI_MacroEllipticArc_H_
+
+#include "SketchAPI.h"
+#include "SketchAPI_MacroEllipse.h"
+
+#include <SketchPlugin_MacroEllipticArc.h>
+
+/// \class SketchAPI_MacroEllipticArc
+/// \ingroup CPPHighAPI
+/// \brief Interface for Elliptic Arc feature.
+class SketchAPI_MacroEllipticArc: public SketchAPI_MacroEllipse
+{
+public:
+ /// Constructor without values.
+ SKETCHAPI_EXPORT
+ explicit SketchAPI_MacroEllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature);
+
+ /// Constructor with values and/or references.
+ SKETCHAPI_EXPORT
+ SketchAPI_MacroEllipticArc(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const ModelHighAPI_RefAttr& theCenterRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theMajorAxisPoint,
+ const ModelHighAPI_RefAttr& theMajorAxisPointRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theArcStart,
+ const ModelHighAPI_RefAttr& theArcStartRef,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theArcEnd,
+ const ModelHighAPI_RefAttr& theArcEndRef,
+ const bool theReversed);
+
+ /// Destructor.
+ SKETCHAPI_EXPORT
+ virtual ~SketchAPI_MacroEllipticArc();
+
+ INTERFACE_3(SketchPlugin_MacroEllipticArc::ID(),
+ startPoint, SketchPlugin_MacroEllipticArc::START_POINT_ID(),
+ GeomDataAPI_Point2D, /** Start point of elliptic arc */,
+ endPoint, SketchPlugin_MacroEllipticArc::END_POINT_ID(),
+ GeomDataAPI_Point2D, /** End point of elliptic arc */,
+ reversed, SketchPlugin_MacroEllipticArc::REVERSED_ID(),
+ ModelAPI_AttributeBoolean, /** Reversed flag for elliptic arc*/)
+};
+
+/// Pointer on Elliptic Arc object.
+typedef std::shared_ptr<SketchAPI_MacroEllipticArc> MacroEllipticArcPtr;
+
+#endif // SketchAPI_MacroEllipticArc_H_
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Point.h>
-#include <SketchAPI_Line.h>
-#include <SketchAPI_Circle.h>
#include <SketchAPI_Arc.h>
+#include <SketchAPI_Circle.h>
+#include <SketchAPI_Ellipse.h>
+#include <SketchAPI_EllipticArc.h>
+#include <SketchAPI_Line.h>
#include <SketchAPI_Point.h>
#include <ModelHighAPI_Dumper.h>
anEntity.reset(new SketchAPI_Circle(aProjectedFeature));
else if (aProjectedFeature->getKind() == SketchPlugin_Arc::ID())
anEntity.reset(new SketchAPI_Arc(aProjectedFeature));
+ else if (aProjectedFeature->getKind() == SketchPlugin_Ellipse::ID())
+ anEntity.reset(new SketchAPI_Ellipse(aProjectedFeature));
+ else if (aProjectedFeature->getKind() == SketchPlugin_EllipticArc::ID())
+ anEntity.reset(new SketchAPI_EllipticArc(aProjectedFeature));
else if (aProjectedFeature->getKind() == SketchPlugin_Point::ID())
anEntity.reset(new SketchAPI_Point(aProjectedFeature));
#include <ModelHighAPI_Tools.h>
//--------------------------------------------------------------------------------------
#include "SketchAPI_Arc.h"
-#include "SketchAPI_MacroArc.h"
#include "SketchAPI_Circle.h"
+#include "SketchAPI_Ellipse.h"
+#include "SketchAPI_EllipticArc.h"
#include "SketchAPI_IntersectionPoint.h"
#include "SketchAPI_Line.h"
+#include "SketchAPI_MacroArc.h"
#include "SketchAPI_MacroCircle.h"
+#include "SketchAPI_MacroEllipse.h"
+#include "SketchAPI_MacroEllipticArc.h"
#include "SketchAPI_Mirror.h"
#include "SketchAPI_Point.h"
#include "SketchAPI_Projection.h"
std::shared_ptr<SketchAPI_Circle> SketchAPI_Sketch::addCircle(const std::string & theExternalName)
{
- // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary?
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_Circle::ID());
return CirclePtr(new SketchAPI_Circle(aFeature, theExternalName));
std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
const ModelHighAPI_RefAttr& theTangentPoint,
double theEndX, double theEndY,
- bool theInversed)
+ bool theInversed,
+ bool theTransversal)
{
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
- return MacroArcPtr(new SketchAPI_MacroArc(
- aFeature, theTangentPoint, theEndX, theEndY, theInversed));
+ MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
+ if (theTransversal)
+ aMacroArc->setByTransversal(theTangentPoint, theEndX, theEndY, theInversed);
+ else
+ aMacroArc->setByTangent(theTangentPoint, theEndX, theEndY, theInversed);
+ return aMacroArc;
}
std::shared_ptr<SketchAPI_MacroArc> SketchAPI_Sketch::addArc(
const ModelHighAPI_RefAttr& theTangentPoint,
const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
- bool theInversed)
+ bool theInversed,
+ bool theTransversal)
{
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_MacroArc::ID());
- return MacroArcPtr(new SketchAPI_MacroArc(aFeature, theTangentPoint, theEnd, theInversed));
+ MacroArcPtr aMacroArc(new SketchAPI_MacroArc(aFeature));
+ if (theTransversal)
+ aMacroArc->setByTransversal(theTangentPoint, theEnd, theInversed);
+ else
+ aMacroArc->setByTangent(theTangentPoint, theEnd, theInversed);
+ return aMacroArc;
}
std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const ModelHighAPI_Selection & theExternal)
std::shared_ptr<SketchAPI_Arc> SketchAPI_Sketch::addArc(const std::string & theExternalName)
{
- // TODO(spo): Add constraint SketchConstraintRigid like in PythonAPI. Is it necessary?
std::shared_ptr<ModelAPI_Feature> aFeature =
compositeFeature()->addFeature(SketchPlugin_Arc::ID());
return ArcPtr(new SketchAPI_Arc(aFeature, theExternalName));
}
+//--------------------------------------------------------------------------------------
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theMinorRadius)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+ return EllipsePtr(new SketchAPI_Ellipse(aFeature,
+ theCenterX, theCenterY, theFocusX, theFocusY, theMinorRadius));
+}
+
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ double theMinorRadius)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+ return EllipsePtr(new SketchAPI_Ellipse(aFeature, theCenter, theFocus, theMinorRadius));
+}
+
+std::shared_ptr<SketchAPI_MacroEllipse> SketchAPI_Sketch::addEllipse(
+ double thePoint1X, double thePoint1Y,
+ double thePoint2X, double thePoint2Y,
+ double thePassedX, double thePassedY,
+ bool isPoint1Center)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID());
+ return MacroEllipsePtr(new SketchAPI_MacroEllipse(aFeature,
+ thePoint1X, thePoint1Y, thePoint2X, thePoint2Y, thePassedX, thePassedY, isPoint1Center));
+}
+
+std::shared_ptr<SketchAPI_MacroEllipse> SketchAPI_Sketch::addEllipse(
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& thePoint1,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& thePoint2,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& thePassedPoint,
+ bool isPoint1Center)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID());
+ MacroEllipsePtr anEllipse;
+ if (thePoint1.second.isEmpty() &&
+ thePoint2.second.isEmpty() &&
+ thePassedPoint.second.isEmpty()) {
+ anEllipse.reset(new SketchAPI_MacroEllipse(aFeature,
+ thePoint1.first, thePoint2.first, thePassedPoint.first, isPoint1Center));
+ }
+ else {
+ anEllipse.reset(new SketchAPI_MacroEllipse(aFeature,
+ thePoint1.first, thePoint1.second,
+ thePoint2.first, thePoint2.second,
+ thePassedPoint.first, thePassedPoint.second,
+ isPoint1Center));
+ }
+ return anEllipse;
+}
+
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+ const ModelHighAPI_Selection & theExternal)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+ return EllipsePtr(new SketchAPI_Ellipse(aFeature, theExternal));
+}
+
+std::shared_ptr<SketchAPI_Ellipse> SketchAPI_Sketch::addEllipse(
+ const std::string & theExternalName)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_Ellipse::ID());
+ return EllipsePtr(new SketchAPI_Ellipse(aFeature, theExternalName));
+}
+
+//--------------------------------------------------------------------------------------
+std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theStartX, double theStartY,
+ double theEndX, double theEndY,
+ bool theInversed)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID());
+ return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature,
+ theCenterX, theCenterY,
+ theFocusX, theFocusY,
+ theStartX, theStartY,
+ theEndX, theEndY,
+ theInversed));
+}
+
+std::shared_ptr<SketchAPI_MacroEllipticArc> SketchAPI_Sketch::addEllipticArc(
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theCenter,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theMajorAxisPoint,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theStartPoint,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theEndPoint,
+ bool theInversed)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_MacroEllipticArc::ID());
+ return MacroEllipticArcPtr(new SketchAPI_MacroEllipticArc(aFeature,
+ theCenter.first, theCenter.second,
+ theMajorAxisPoint.first, theMajorAxisPoint.second,
+ theStartPoint.first, theStartPoint.second,
+ theEndPoint.first, theEndPoint.second,
+ theInversed));
+}
+
+std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
+ const ModelHighAPI_Selection & theExternal)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID());
+ return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, theExternal));
+}
+
+std::shared_ptr<SketchAPI_EllipticArc> SketchAPI_Sketch::addEllipticArc(
+ const std::string & theExternalName)
+{
+ std::shared_ptr<ModelAPI_Feature> aFeature =
+ compositeFeature()->addFeature(SketchPlugin_EllipticArc::ID());
+ return EllipticArcPtr(new SketchAPI_EllipticArc(aFeature, theExternalName));
+}
+
//--------------------------------------------------------------------------------------
std::shared_ptr<SketchAPI_Projection> SketchAPI_Sketch::addProjection(
const ModelHighAPI_Selection & theExternalFeature,
return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(x, y));
}
+static std::shared_ptr<GeomAPI_Pnt2d> pointOnEllipse(const FeaturePtr& theFeature)
+{
+ AttributePoint2DPtr aMajorAxisEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()));
+ return aMajorAxisEnd ? aMajorAxisEnd->pnt() : std::shared_ptr<GeomAPI_Pnt2d>();
+}
+
static std::shared_ptr<GeomAPI_Pnt2d> middlePoint(const ObjectPtr& theObject)
{
std::shared_ptr<GeomAPI_Pnt2d> aMiddlePoint;
aMiddlePoint = pointOnCircle(aFeature);
else if (aFeatureKind == SketchPlugin_Arc::ID())
aMiddlePoint = middlePointOnArc(aFeature);
+ else if (aFeatureKind == SketchPlugin_Ellipse::ID())
+ aMiddlePoint = pointOnEllipse(aFeature);
}
return aMiddlePoint;
}
class SketchAPI_MacroArc;
class SketchAPI_Circle;
class SketchAPI_MacroCircle;
+class SketchAPI_Ellipse;
+class SketchAPI_MacroEllipse;
+class SketchAPI_EllipticArc;
+class SketchAPI_MacroEllipticArc;
class SketchAPI_IntersectionPoint;
class SketchAPI_Line;
class SketchAPI_Mirror;
const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
const std::shared_ptr<GeomAPI_Pnt2d>& thePassed);
- /// Add arc
+ /// Add transversal/tangent arc
SKETCHAPI_EXPORT
std::shared_ptr<SketchAPI_MacroArc> addArc(
- const ModelHighAPI_RefAttr& theTangentPoint,
+ const ModelHighAPI_RefAttr& theConnectedPoint,
double theEndX, double theEndY,
- bool theInversed);
+ bool theInversed,
+ bool theTransversal = false);
- /// Add arc
+ /// Add transversal/tangent arc
SKETCHAPI_EXPORT
std::shared_ptr<SketchAPI_MacroArc> addArc(
- const ModelHighAPI_RefAttr& theTangentPoint,
+ const ModelHighAPI_RefAttr& theConnectedPoint,
const std::shared_ptr<GeomAPI_Pnt2d>& theEnd,
- bool theInversed);
+ bool theInversed,
+ bool theTransversal = false);
/// Add arc
SKETCHAPI_EXPORT
SKETCHAPI_EXPORT
std::shared_ptr<SketchAPI_Arc> addArc(const std::string & theExternalName);
+ /// Add ellipse
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_Ellipse> addEllipse(
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theMinorRadius);
+ /// Add ellipse
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_Ellipse> addEllipse(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theCenter,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFocus,
+ double theRadius);
+ /// Add ellipse
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_MacroEllipse> addEllipse(
+ double thePoint1X, double thePoint1Y,
+ double thePoint2X, double thePoint2Y,
+ double thePassedX, double thePassedY,
+ bool isPoint1Center = true);
+ /// Add ellipse
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_MacroEllipse> addEllipse(
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& thePoint1,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& thePoint2,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& thePassedPoint,
+ bool isPoint1Center = true);
+ /// Add ellipse
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_Ellipse> addEllipse(const ModelHighAPI_Selection & theExternal);
+ /// Add ellipse
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_Ellipse> addEllipse(const std::string & theExternalName);
+
+ /// Add elliptic arc
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_EllipticArc> addEllipticArc(
+ double theCenterX, double theCenterY,
+ double theFocusX, double theFocusY,
+ double theStartX, double theStartY,
+ double theEndX, double theEndY,
+ bool theInversed = false);
+ /// Add elliptic arc
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_MacroEllipticArc> addEllipticArc(
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theCenter,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theMajorAxisPoint,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theStartPoint,
+ const std::pair<std::shared_ptr<GeomAPI_Pnt2d>, ModelHighAPI_RefAttr>& theEndPoint,
+ bool theInversed = false);
+ /// Add elliptic arc
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_EllipticArc> addEllipticArc(const ModelHighAPI_Selection & theExternal);
+ /// Add elliptic arc
+ SKETCHAPI_EXPORT
+ std::shared_ptr<SketchAPI_EllipticArc> addEllipticArc(const std::string & theExternalName);
+
/// Add projection
SKETCHAPI_EXPORT
std::shared_ptr<SketchAPI_Projection> addProjection(
#include "SketchAPI_SketchEntity.h"
#include <SketchAPI_Arc.h>
#include <SketchAPI_Circle.h>
+#include <SketchAPI_Ellipse.h>
+#include <SketchAPI_EllipticArc.h>
#include <SketchAPI_IntersectionPoint.h>
#include <SketchAPI_Line.h>
#include <SketchAPI_Point.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_IntersectionPoint.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_Arc(*anIt)));
else if ((*anIt)->getKind() == SketchPlugin_Circle::ID())
aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_Circle(*anIt)));
+ else if ((*anIt)->getKind() == SketchPlugin_Ellipse::ID())
+ aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_Ellipse(*anIt)));
+ else if ((*anIt)->getKind() == SketchPlugin_EllipticArc::ID())
+ aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_EllipticArc(*anIt)));
else if ((*anIt)->getKind() == SketchPlugin_Point::ID())
aResult.push_back(std::shared_ptr<SketchAPI_SketchEntity>(new SketchAPI_Point(*anIt)));
else if ((*anIt)->getKind() == SketchPlugin_IntersectionPoint::ID())
#include "SketchAPI_MacroArc.h"
#include "SketchAPI_Circle.h"
#include "SketchAPI_MacroCircle.h"
+ #include "SketchAPI_Ellipse.h"
+ #include "SketchAPI_MacroEllipse.h"
+ #include "SketchAPI_EllipticArc.h"
+ #include "SketchAPI_MacroEllipticArc.h"
#include "SketchAPI_Constraint.h"
#include "SketchAPI_ConstraintAngle.h"
#include "SketchAPI_IntersectionPoint.h"
SketchPlugin_ConstraintAngle.h
SketchPlugin_ConstraintBase.h
SketchPlugin_ConstraintCoincidence.h
+ SketchPlugin_ConstraintCoincidenceInternal.h
SketchPlugin_ConstraintCollinear.h
SketchPlugin_ConstraintDistance.h
SketchPlugin_ConstraintDistanceAlongDir.h
SketchPlugin_ConstraintTangent.h
SketchPlugin_ConstraintVertical.h
SketchPlugin_Ellipse.h
+ SketchPlugin_EllipticArc.h
SketchPlugin_ExternalValidator.h
SketchPlugin_Feature.h
SketchPlugin_IntersectionPoint.h
SketchPlugin_MacroArcReentrantMessage.h
SketchPlugin_MacroCircle.h
SketchPlugin_MacroEllipse.h
+ SketchPlugin_MacroEllipticArc.h
SketchPlugin_MultiRotation.h
SketchPlugin_MultiTranslation.h
SketchPlugin_Plugin.h
SketchPlugin_Constraint.cpp
SketchPlugin_ConstraintAngle.cpp
SketchPlugin_ConstraintCoincidence.cpp
+ SketchPlugin_ConstraintCoincidenceInternal.cpp
SketchPlugin_ConstraintCollinear.cpp
SketchPlugin_ConstraintDistance.cpp
SketchPlugin_ConstraintDistanceAlongDir.cpp
SketchPlugin_ConstraintTangent.cpp
SketchPlugin_ConstraintVertical.cpp
SketchPlugin_Ellipse.cpp
+ SketchPlugin_EllipticArc.cpp
SketchPlugin_ExternalValidator.cpp
SketchPlugin_Feature.cpp
SketchPlugin_IntersectionPoint.cpp
SketchPlugin_MacroArc.cpp
SketchPlugin_MacroCircle.cpp
SketchPlugin_MacroEllipse.cpp
+ SketchPlugin_MacroEllipticArc.cpp
SketchPlugin_MultiRotation.cpp
SketchPlugin_MultiTranslation.cpp
SketchPlugin_Plugin.cpp
SET(TEXT_RESOURCES
SketchPlugin_msg_en.ts
+ SketchPlugin_msg_fr.ts
)
SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
Test2824.py
Test2860.py
Test2894.py
+ Test3019.py
TestArcBehavior.py
TestChangeSketchPlane1.py
TestChangeSketchPlane2.py
TestChangeSketchPlane3.py
+ TestChangeSketchPlane4.py
TestConstraintAngle.py
+ TestConstraintAngleEllipse.py
TestConstraintCoincidence.py
+ TestConstraintCoincidenceEllipse.py
+ TestConstraintCoincidenceEllipticArc.py
TestConstraintCollinear.py
+ TestConstraintCollinearEllipse.py
TestConstraintDistance.py
+ TestConstraintDistanceEllipse.py
TestConstraintDistanceBehavior.py
TestConstraintDistanceHorizontal.py
TestConstraintDistanceVertical.py
TestConstraintEqual.py
+ TestConstraintEqualEllipse.py
TestConstraintFixed.py
TestConstraintHorizontal.py
TestConstraintHorizontalValidator.py
TestConstraintLength.py
TestConstraintMiddlePoint.py
+ TestConstraintMiddlePointOnArc.py
+ TestConstraintMiddlePointOnEllipticArc.py
TestConstraintParallel.py
TestConstraintPerpendicular.py
+ TestConstraintPerpendicularArcLine.py
+ TestConstraintPerpendicularEllipseLine.py
TestConstraintRadius.py
TestConstraintRadiusFailure.py
TestConstraintTangent.py
+ TestConstraintTangentEllipse.py
+ TestConstraintTangentEllipticArc.py
TestConstraintVertical.py
TestCreateArcByCenterStartEnd.py
TestCreateArcByTangentEdge.py
TestCreateArcByThreePoints.py
+ TestCreateArcByTransversalLine.py
TestCreateArcChangeType.py
TestCreateCircleByCenterAndPassed.py
TestCreateCircleByThreePoints.py
TestCreateCircleChangeType.py
+ TestCreateEllipseByCenterSemiaxisAndPassed.py
+ TestCreateEllipseByMajorAxisAndPassed.py
+ TestCreateEllipseByExternal.py
+ TestCreateEllipticArc.py
+ TestCreateEllipticArcByExternal.py
TestDegeneratedGeometry.py
TestDistanceDump.py
TestDistanceSignedVsUnsigned01.py
TestMultiTranslation.py
TestPresentation.py
TestProjection.py
+ TestProjectionEllipse.py
+ TestProjectionEllipticArc.py
TestProjectionIntoResult.py
TestProjectionUpdate.py
TestRectangle.py
+ TestRemoveEllipse.py
+ TestRemoveEllipticArc.py
TestRemoveSketch.py
TestSignedDistancePointLine.py
TestSignedDistancePointPoint.py
TestSketchPointLine.py
TestSnowflake.py
TestSplit.py
+ TestSplitEllipse.py
TestSplitLine.py
TestSplitPreview.py
TestTrimArc01.py
TestTrimCircle04.py
TestTrimCircle05.py
TestTrimCircleAndArc01.py
+ TestTrimEllipse.py
TestTrimLine01.py
TestTrimLine02.py
TestTrimLine03.py
ADD_UNIT_TESTS(
TestMoveArc.py
TestMoveCircle.py
+ TestMoveEllipse.py
TestMoveLine.py
TestMovementComplex.py
TestMovePoint.py
// for sqrt on Linux
#include <cmath>
-const double tolerance = 1e-7;
-const double paramTolerance = 1.e-4;
-const double PI = 3.141592653589793238463;
+static const double tolerance = 1e-7;
+static const double paramTolerance = 1.e-4;
+static const double PI = 3.141592653589793238463;
SketchPlugin_Arc::SketchPlugin_Arc()
--- /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
+//
+
+#include "SketchPlugin_ConstraintCoincidenceInternal.h"
+
+SketchPlugin_ConstraintCoincidenceInternal::SketchPlugin_ConstraintCoincidenceInternal()
+{
+}
+
+void SketchPlugin_ConstraintCoincidenceInternal::initAttributes()
+{
+ SketchPlugin_ConstraintCoincidence::initAttributes();
+}
+
+void SketchPlugin_ConstraintCoincidenceInternal::execute()
+{
+}
+
+AISObjectPtr SketchPlugin_ConstraintCoincidenceInternal::getAISObject(AISObjectPtr thePrevious)
+{
+ return AISObjectPtr();
+}
--- /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
+//
+
+#ifndef SketchPlugin_ConstraintCoincidenceInternal_H_
+#define SketchPlugin_ConstraintCoincidenceInternal_H_
+
+#include "SketchPlugin.h"
+#include "SketchPlugin_ConstraintCoincidence.h"
+
+/** \class SketchPlugin_ConstraintCoincidenceInternal
+ * \ingroup Plugins
+ * \brief Internal coincidence constraint not applicable for the end user
+ */
+class SketchPlugin_ConstraintCoincidenceInternal : public SketchPlugin_ConstraintCoincidence
+{
+ public:
+ /// Coincidence constraint kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_COINCIDENCE_ID("SketchConstraintCoincidenceInternal");
+ return MY_CONSTRAINT_COINCIDENCE_ID;
+ }
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_ConstraintCoincidenceInternal::ID();
+ return MY_KIND;
+ }
+
+ /// Returns the AIS preview
+ SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// \brief Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_ConstraintCoincidenceInternal();
+};
+
+#endif
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_Ellipse.cpp
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Sketch.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Dir2d.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Pnt2d.h>
+
#include <GeomDataAPI_Point2D.h>
+
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
+#include <cmath>
+
static const double tolerance = 1e-7;
void SketchPlugin_Ellipse::initDerivedClassAttributes()
{
data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
- data()->addAttribute(FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(FIRST_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SECOND_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_FOCUS_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_START_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_END_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_START_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_END_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_RADIUS_ID());
+
data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
}
return;
}
- // Compute a ellipse in 3D view.
- std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FOCUS_ID()));
- AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
- AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
- if (!aCenterAttr->isInitialized() ||
- !aFocusAttr->isInitialized() ||
- !aMajorRadiusAttr->isInitialized() ||
- !aMinorRadiusAttr->isInitialized()) {
- return;
- }
-
- double aMajorRadius = aMajorRadiusAttr->value();
- double aMinorRadius = aMinorRadiusAttr->value();
- if(aMajorRadius < tolerance || aMinorRadius < tolerance) {
- return;
- }
-
- // Make a visible point.
- SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), 0);
-
- std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+ // Calculate all characteristics of the ellipse.
+ fillCharacteristicPoints();
// Make a visible ellipse.
- std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
- std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
- std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
- std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
- aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
-
- std::shared_ptr<GeomAPI_Shape> anEllipseShape =
- GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
-
- std::shared_ptr<ModelAPI_ResultConstruction> aResult = document()->createConstruction(data(), 1);
- aResult->setShape(anEllipseShape);
- aResult->setIsInHistory(false);
- setResult(aResult, 1);
+ createEllipse(aSketch, 0);
}
bool SketchPlugin_Ellipse::isFixed() {
aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FOCUS_ID()));
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_FOCUS_ID()));
aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
}
}
}
+
+bool SketchPlugin_Ellipse::fillCharacteristicPoints()
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+
+ if (!aCenterAttr->isInitialized() ||
+ !aFocusAttr->isInitialized() ||
+ !aMinorRadiusAttr->isInitialized()) {
+ return false;
+ }
+
+ double aMinorRadius = aMinorRadiusAttr->value();
+ if (aMinorRadius < tolerance) {
+ return false;
+ }
+
+ data()->blockSendAttributeUpdated(true);
+ GeomPnt2dPtr aCenter2d = aCenterAttr->pnt();
+ GeomPnt2dPtr aFocus2d = aFocusAttr->pnt();
+ GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(),
+ aFocus2d->y() - aCenter2d->y()));
+ GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x()));
+
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ double aFocalDist = aCenter2d->distance(aFocus2d);
+ double aMajorRadius = sqrt(aFocalDist * aFocalDist + aMinorRadius * aMinorRadius);
+ aMajorRadiusAttr->setValue(aMajorRadius);
+
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_FOCUS_ID()))
+ ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y());
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() - aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() + aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() - aMinorDir2d->y() * aMinorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
+ data()->blockSendAttributeUpdated(false);
+
+ return true;
+}
+
+void SketchPlugin_Ellipse::createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex)
+{
+ // Compute a ellipse in 3D view.
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ double aMajorRadius = real(MAJOR_RADIUS_ID())->value();
+ double aMinorRadius = real(MINOR_RADIUS_ID())->value();
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+ GeomPointPtr aCenter(theSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+ GeomPointPtr aFocus(theSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+ GeomDirPtr aNormal = aNDir->dir();
+ std::shared_ptr<GeomAPI_Shape> anEllipseShape;
+ if (aFocus->distance(aCenter) > tolerance) {
+ GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+ anEllipseShape =
+ GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxis, aMajorRadius, aMinorRadius);
+ }
+ else {
+ // build circle instead of ellipse
+ anEllipseShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aMajorRadius);
+ }
+
+ ResultConstructionPtr aResult = document()->createConstruction(data(), theResultIndex);
+ aResult->setShape(anEllipseShape);
+ aResult->setIsInHistory(false);
+ setResult(aResult, theResultIndex);
+}
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_Ellipse.h
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#ifndef SketchPlugin_Ellipse_H_
#define SketchPlugin_Ellipse_H_
}
/// 2D point - focus of the ellipse
- inline static const std::string& FOCUS_ID()
+ inline static const std::string& FIRST_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_first_focus");
+ return ID;
+ }
+ /// 2D point - second focus of the ellipse
+ inline static const std::string& SECOND_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_second_focus");
+ return ID;
+ }
+
+ /// 2D point - start point of major axis
+ inline static const std::string& MAJOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_major_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of major axis
+ inline static const std::string& MAJOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_major_axis_end_point");
+ return ID;
+ }
+
+ /// 2D point - start point of minor axis
+ inline static const std::string& MINOR_AXIS_START_ID()
{
- static const std::string ID("ellipse_focus");
+ static const std::string ID("ellipse_minor_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of minor axis
+ inline static const std::string& MINOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_end_point");
return ID;
}
protected:
/// \brief Initializes attributes of derived class.
virtual void initDerivedClassAttributes();
+
+private:
+ bool fillCharacteristicPoints();
+
+ void createEllipse(SketchPlugin_Sketch* theSketch, const int theResultIndex);
};
#endif
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <SketchPlugin_EllipticArc.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <GeomAlgoAPI_EdgeBuilder.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <cmath>
+
+static const double tolerance = 1e-7;
+static const double paramTolerance = 1.e-4;
+static const double PI = 3.141592653589793238463;
+
+
+SketchPlugin_EllipticArc::SketchPlugin_EllipticArc()
+ : SketchPlugin_SketchEntity(),
+ myParamDelta(0.0)
+{
+}
+
+void SketchPlugin_EllipticArc::initDerivedClassAttributes()
+{
+ data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(FIRST_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(SECOND_FOCUS_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MINOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId());
+
+ data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SECOND_FOCUS_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_START_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_END_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_START_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_AXIS_END_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_RADIUS_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MINOR_RADIUS_ID());
+
+ data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+}
+
+void SketchPlugin_EllipticArc::execute()
+{
+ SketchPlugin_Sketch* aSketch = sketch();
+ if(!aSketch) {
+ return;
+ }
+
+ // Calculate all characteristics of the ellipse.
+ fillCharacteristicPoints();
+
+ // Make a visible ellipse.
+ createEllipticArc(aSketch);
+}
+
+bool SketchPlugin_EllipticArc::isFixed() {
+ return data()->selection(EXTERNAL_ID())->context().get() != NULL;
+}
+
+void SketchPlugin_EllipticArc::attributeChanged(const std::string& theID) {
+ // the second condition for unability to move external segments anywhere
+ if (theID == EXTERNAL_ID() || isFixed()) {
+ std::shared_ptr<GeomAPI_Shape> aSelection = data()->selection(EXTERNAL_ID())->value();
+ if (!aSelection) {
+ // empty shape in selection shows that the shape is equal to context
+ ResultPtr anExtRes = selection(EXTERNAL_ID())->context();
+ if (anExtRes)
+ aSelection = anExtRes->shape();
+ }
+ // update arguments due to the selection value
+ if (aSelection && !aSelection->isNull() && aSelection->isEdge()) {
+ std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aSelection));
+ std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
+
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_ID()));
+ aCenterAttr->setValue(sketch()->to2D(anEllipse->center()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(FIRST_FOCUS_ID()));
+ aFocusAttr->setValue(sketch()->to2D(anEllipse->firstFocus()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(START_POINT_ID()));
+ aStartAttr->setValue(sketch()->to2D(anEdge->firstPoint()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(END_POINT_ID()));
+ aEndAttr->setValue(sketch()->to2D(anEdge->lastPoint()));
+
+ real(MAJOR_RADIUS_ID())->setValue(anEllipse->majorRadius());
+ real(MINOR_RADIUS_ID())->setValue(anEllipse->minorRadius());
+
+ double aStartParam, aMidParam, aEndParam;
+ anEllipse->parameter(anEdge->firstPoint(), tolerance, aStartParam);
+ anEllipse->parameter(anEdge->middlePoint(), tolerance, aMidParam);
+ anEllipse->parameter(anEdge->lastPoint(), tolerance, aEndParam);
+ if (aEndParam < aStartParam)
+ aEndParam += 2.0 * PI;
+ if (aMidParam < aStartParam)
+ aMidParam += 2.0 * PI;
+ boolean(REVERSED_ID())->setValue(aMidParam > aEndParam);
+
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+
+ fillCharacteristicPoints();
+ }
+ }
+ else if (theID == CENTER_ID() || theID == FIRST_FOCUS_ID() ||
+ theID == START_POINT_ID() || theID == END_POINT_ID())
+ fillCharacteristicPoints();
+ else if (theID == REVERSED_ID() && myParamDelta == 0.0)
+ myParamDelta = 2.0 * PI;
+}
+
+static void calculateRadii(const GeomPnt2dPtr& theCenter,
+ const GeomPnt2dPtr& theFocus,
+ const GeomPnt2dPtr& thePassed,
+ double& theMajorRadius,
+ double& theMinorRadius)
+{
+ GeomPnt2dPtr aSecondFocus(new GeomAPI_Pnt2d(
+ theCenter->xy()->multiplied(2.0)->decreased(theFocus->xy())));
+ theMajorRadius = 0.5 * (thePassed->distance(theFocus) + thePassed->distance(aSecondFocus));
+
+ double aFocalDist = theCenter->distance(theFocus);
+ theMinorRadius = sqrt(theMajorRadius * theMajorRadius - aFocalDist * aFocalDist);
+}
+
+bool SketchPlugin_EllipticArc::fillCharacteristicPoints()
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_POINT_ID()));
+
+ if (!aCenterAttr->isInitialized() ||
+ !aFocusAttr->isInitialized() ||
+ !aStartPointAttr->isInitialized()) {
+ return false;
+ }
+
+ GeomPnt2dPtr aCenter2d = aCenterAttr->pnt();
+ GeomPnt2dPtr aFocus2d = aFocusAttr->pnt();
+ GeomPnt2dPtr aStart2d = aStartPointAttr->pnt();
+
+ double aMajorRadius = 0.0, aMinorRadius = 0.0;
+ calculateRadii(aCenter2d, aFocus2d, aStart2d, aMajorRadius, aMinorRadius);
+ if (aMinorRadius < tolerance * aMajorRadius)
+ return false;
+
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ real(MAJOR_RADIUS_ID())->setValue(aMajorRadius);
+ real(MINOR_RADIUS_ID())->setValue(aMinorRadius);
+
+ GeomDir2dPtr aMajorDir2d(new GeomAPI_Dir2d(aFocus2d->x() - aCenter2d->x(),
+ aFocus2d->y() - aCenter2d->y()));
+ GeomDir2dPtr aMinorDir2d(new GeomAPI_Dir2d(-aMajorDir2d->y(), aMajorDir2d->x()));
+
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(SECOND_FOCUS_ID()))
+ ->setValue(2.0 * aCenter2d->x() - aFocus2d->x(), 2.0 * aCenter2d->y() - aFocus2d->y());
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() - aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MAJOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMajorDir2d->x() * aMajorRadius,
+ aCenter2d->y() + aMajorDir2d->y() * aMajorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_START_ID()))
+ ->setValue(aCenter2d->x() - aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() - aMinorDir2d->y() * aMinorRadius);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(MINOR_AXIS_END_ID()))
+ ->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
+ aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
+
+ if (aEndPointAttr->isInitialized()) {
+ // recalculate REVERSED flag
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipseForArc(
+ new GeomAPI_Ellipse2d(aCenter2d, aMajorDir2d, aMajorRadius, aMinorRadius));
+ GeomPnt2dPtr anEnd = aEndPointAttr->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aProjection = anEllipseForArc->project(anEnd);
+ double aParamStart = 0.0, aParamEnd = 0.0;
+ if (aProjection && anEnd->distance(aProjection) <= tolerance &&
+ anEllipseForArc->parameter(anEnd, paramTolerance, aParamEnd)) {
+ // do not recalculate REVERSED flag if the arc is not consistent
+ anEllipseForArc->parameter(aStart2d, paramTolerance, aParamStart);
+ aParamEnd -= aParamStart;
+
+ if (myParamDelta >= 0.0 && myParamDelta <= PI * 0.5 &&
+ aParamEnd < 0.0 && aParamEnd >= -PI * 0.5) {
+ boolean(REVERSED_ID())->setValue(true);
+ }
+ else if (myParamDelta <= 0.0 && myParamDelta >= -PI * 0.5 &&
+ aParamEnd > 0.0 && aParamEnd <= PI * 0.5) {
+ boolean(REVERSED_ID())->setValue(false);
+ }
+ myParamDelta = aParamEnd;
+ }
+ }
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+
+ return true;
+}
+
+void SketchPlugin_EllipticArc::createEllipticArc(SketchPlugin_Sketch* theSketch)
+{
+ // Compute a ellipse in 3D view.
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
+
+ double aMajorRadius = real(MAJOR_RADIUS_ID())->value();
+ double aMinorRadius = real(MINOR_RADIUS_ID())->value();
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ theSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+
+ GeomPointPtr aCenter(theSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
+ GeomPointPtr aFocus(theSketch->to3D(aFocusAttr->x(), aFocusAttr->y()));
+ GeomDirPtr aNormal = aNDir->dir();
+ std::shared_ptr<GeomAPI_Shape> anEllipseShape;
+ if (aFocus->distance(aCenter) > tolerance) {
+ GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
+
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_POINT_ID()));
+
+ GeomPointPtr aStartPnt(theSketch->to3D(aStartAttr->x(), aStartAttr->y()));
+ GeomPointPtr aEndPnt(theSketch->to3D(aEndAttr->x(), aEndAttr->y()));
+ if (boolean(REVERSED_ID())->value())
+ std::swap(aStartPnt, aEndPnt);
+
+ anEllipseShape = GeomAlgoAPI_EdgeBuilder::ellipticArc(aCenter, aNormal, aMajorAxis,
+ aMajorRadius, aMinorRadius, aStartPnt, aEndPnt);
+ }
+ else {
+ // build circle instead of ellipse
+ anEllipseShape = GeomAlgoAPI_EdgeBuilder::lineCircle(aCenter, aNormal, aMajorRadius);
+ }
+
+ ResultConstructionPtr aResult = document()->createConstruction(data());
+ aResult->setShape(anEllipseShape);
+ aResult->setIsInHistory(false);
+ setResult(aResult);
+}
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SketchPlugin_EllipticArc_H_
+#define SketchPlugin_EllipticArc_H_
+
+#include <SketchPlugin.h>
+#include <SketchPlugin_SketchEntity.h>
+
+/**\class SketchPlugin_EllipticArc
+ * \ingroup Plugins
+ * \brief Feature for creation of the new elliptic arc in Sketch.
+ */
+class SketchPlugin_EllipticArc: public SketchPlugin_SketchEntity
+{
+ public:
+ /// Ellipse feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string ID("SketchEllipticArc");
+ return ID;
+ }
+
+ /// 2D point - center of the ellipse
+ inline static const std::string& CENTER_ID()
+ {
+ static const std::string ID("ellipse_center");
+ return ID;
+ }
+
+ /// 2D point - start point of elliptic arc
+ inline static const std::string& START_POINT_ID()
+ {
+ static const std::string ID("start_point");
+ return ID;
+ }
+ /// 2D point - end point of elliptic arc
+ inline static const std::string& END_POINT_ID()
+ {
+ static const std::string ID("end_point");
+ return ID;
+ }
+
+ /// 2D point - focus of the ellipse
+ inline static const std::string& FIRST_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_first_focus");
+ return ID;
+ }
+ /// 2D point - second focus of the ellipse
+ inline static const std::string& SECOND_FOCUS_ID()
+ {
+ static const std::string ID("ellipse_second_focus");
+ return ID;
+ }
+
+ /// 2D point - start point of major axis
+ inline static const std::string& MAJOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_major_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of major axis
+ inline static const std::string& MAJOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_major_axis_end_point");
+ return ID;
+ }
+
+ /// 2D point - start point of minor axis
+ inline static const std::string& MINOR_AXIS_START_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_start_point");
+ return ID;
+ }
+ /// 2D point - end point of minor axis
+ inline static const std::string& MINOR_AXIS_END_ID()
+ {
+ static const std::string ID("ellipse_minor_axis_end_point");
+ return ID;
+ }
+
+ /// Major radius of the ellipse
+ inline static const std::string& MAJOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_major_radius");
+ return ID;
+ }
+
+ /// Minor radius of the ellipse
+ inline static const std::string& MINOR_RADIUS_ID()
+ {
+ static const std::string ID("ellipse_minor_radius");
+ return ID;
+ }
+
+ /// Flag the arc is reversed
+ inline static const std::string& REVERSED_ID()
+ {
+ static const std::string ID("reversed");
+ return ID;
+ }
+
+ /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_EllipticArc::ID();
+ return MY_KIND;
+ }
+
+ /// Returns true is sketch element is under the rigid constraint
+ SKETCHPLUGIN_EXPORT virtual bool isFixed();
+
+ /// Called on change of any argument-attribute of this object
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Use plugin manager for features creation
+ SketchPlugin_EllipticArc();
+
+protected:
+ /// \brief Initializes attributes of derived class.
+ virtual void initDerivedClassAttributes();
+
+private:
+ bool fillCharacteristicPoints();
+
+ void createEllipticArc(SketchPlugin_Sketch* theSketch);
+
+private:
+ double myParamDelta;
+};
+
+#endif
#include <ModelAPI_Validator.h>
#include <ModelAPI_Session.h>
-#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Edge.h>
#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt.h>
#include <GeomAPI_Pnt2d.h>
-#include <GeomAlgoAPI_EdgeBuilder.h>
#include <GeomDataAPI_Point2D.h>
SketchPlugin_Line::SketchPlugin_Line()
/// new attributes should be added to end of the feature in order to provide
/// correct attribute values in previous saved studies
data()->addAttribute(LENGTH_ID(), ModelAPI_AttributeDouble::typeId());
+
+ data()->addAttribute(PARENT_ID(), ModelAPI_AttributeReference::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PARENT_ID());
}
void SketchPlugin_Line::initDerivedClassAttributes()
std::shared_ptr<GeomDataAPI_Point2D> anEndAttr = std::dynamic_pointer_cast<
GeomDataAPI_Point2D>(data()->attribute(END_ID()));
if (aStartAttr->isInitialized() && anEndAttr->isInitialized()) {
- std::shared_ptr<GeomAPI_Pnt> aStart(aSketch->to3D(aStartAttr->x(), aStartAttr->y()));
- std::shared_ptr<GeomAPI_Pnt> anEnd(aSketch->to3D(anEndAttr->x(), anEndAttr->y()));
- //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
- // <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
- // make linear edge
- std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
- // store the result
- std::shared_ptr<ModelAPI_ResultConstruction> aConstr = document()->createConstruction(
- data());
- aConstr->setShape(anEdge);
- aConstr->setIsInHistory(false);
- setResult(aConstr);
+ SketchPlugin_Sketch::createLine2DResult(this, aSketch, START_ID(), END_ID());
static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
std::shared_ptr<ModelAPI_EventReentrantMessage> aMessage = std::shared_ptr
return MY_LENGTH;
}
+ /// Reference to the parent feature
+ inline static const std::string& PARENT_ID()
+ {
+ static const std::string& MY_PARENT_ID("ParentFeature");
+ return MY_PARENT_ID;
+ }
+
/// Returns the kind of a feature
SKETCHPLUGIN_EXPORT virtual const std::string& getKind();
#include "SketchPlugin_MacroArc.h"
#include "SketchPlugin_Arc.h"
+#include "SketchPlugin_ConstraintPerpendicular.h"
#include "SketchPlugin_ConstraintTangent.h"
#include "SketchPlugin_Sketch.h"
#include "SketchPlugin_Tools.h"
else if(anArcType == ARC_TYPE_BY_THREE_POINTS())
fillByThreePassedPoints();
else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE())
- fillByTangentEdge();
+ fillByEdge(false);
+ else if (anArcType == ARC_TYPE_BY_TRANSVERSAL_LINE())
+ fillByEdge(true);
double aRadius = 0;
double anAngle = 0;
AttributePtr(),
anArcFeature->lastResult(),
true);
- } else if(anArcType == ARC_TYPE_BY_TANGENT_EDGE()) {
- // constraints for tangent arc
+ } else {
+ // coincident with connection point
SketchPlugin_Tools::createCoincidenceOrTangency(this,
TANGENT_POINT_ID(),
anArcFeature->attribute(SketchPlugin_Arc::START_ID()),
ObjectPtr(),
false);
- FeaturePtr aTangent = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID());
- AttributeRefAttrPtr aRefAttrA = aTangent->refattr(SketchPlugin_Constraint::ENTITY_A());
+ // tangent or perpendicular constraint
+ FeaturePtr aStartPointConstraint;
+ if (anArcType == ARC_TYPE_BY_TANGENT_EDGE())
+ aStartPointConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID());
+ else
+ aStartPointConstraint = sketch()->addFeature(SketchPlugin_ConstraintPerpendicular::ID());
+ // setting attributes of the start point constraint
+ AttributeRefAttrPtr aRefAttrA =
+ aStartPointConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
AttributeRefAttrPtr aTgPntRefAttr = refattr(TANGENT_POINT_ID());
FeaturePtr aTgFeature = ModelAPI_Feature::feature(aTgPntRefAttr->attr()->owner());
aRefAttrA->setObject(aTgFeature->lastResult());
- AttributeRefAttrPtr aRefAttrB = aTangent->refattr(SketchPlugin_Constraint::ENTITY_B());
+ AttributeRefAttrPtr aRefAttrB =
+ aStartPointConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
aRefAttrB->setObject(anArcFeature->lastResult());
// constraint for end point
SketchPlugin_Tools::createCoincidenceOrTangency(this,
myParamBefore = aEndParam;
}
-void SketchPlugin_MacroArc::fillByTangentEdge()
+void SketchPlugin_MacroArc::fillByEdge(bool theTransversal)
{
AttributeRefAttrPtr aTangentAttr = refattr(TANGENT_POINT_ID());
if (!aTangentAttr->isInitialized())
return;
- AttributePoint2DPtr aTangentPointAttr =
+ AttributePoint2DPtr aConnectionPointAttr =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aTangentAttr->attr());
- if (!aTangentPointAttr->isInitialized())
+ if (!aConnectionPointAttr->isInitialized())
return;
AttributePoint2DPtr anEndPointAttr =
if (!anEndPointAttr->isInitialized())
return;
- myStart = aTangentPointAttr->pnt();
+ myStart = aConnectionPointAttr->pnt();
myEnd = anEndPointAttr->pnt();
if (myStart->isEqual(myEnd))
return;
// obtain a shape the tangent point belongs to
- FeaturePtr aTangentFeature = ModelAPI_Feature::feature(aTangentPointAttr->owner());
- std::shared_ptr<GeomAPI_Shape> aTangentShape = aTangentFeature->lastResult()->shape();
+ FeaturePtr aConnectedFeature = ModelAPI_Feature::feature(aConnectionPointAttr->owner());
+ std::shared_ptr<GeomAPI_Shape> aTangentShape = aConnectedFeature->lastResult()->shape();
GeomAlgoAPI_Circ2dBuilder aCircBuilder(SketchPlugin_Sketch::plane(sketch()));
aCircBuilder.addPassingPoint(myStart);
aCircBuilder.addPassingPoint(myEnd);
- aCircBuilder.addTangentCurve(aTangentShape);
+ if (theTransversal)
+ aCircBuilder.setTransversalLine(aTangentShape);
+ else
+ aCircBuilder.addTangentCurve(aTangentShape);
std::shared_ptr<GeomAPI_Circ2d> aCircle = aCircBuilder.circle();
if (!aCircle)
return ID;
}
+ inline static const std::string& ARC_TYPE_BY_TRANSVERSAL_LINE()
+ {
+ static const std::string ID("by_transversal_line");
+ return ID;
+ }
+
/// Central 2D point of the circle which contains the arc
inline static const std::string& CENTER_POINT_ID()
{
void fillByCenterAndTwoPassed();
/// Set fields for center, start and end points by selected passed points
void fillByThreePassedPoints();
- /// Set fields for center, start and end points by selected tangent edge
- void fillByTangentEdge();
+ /// Set fields for center, start and end points by selected tangent or transversal edge
+ /// \param theTransversal if \c true, builds transversal arc, otherwise builds tangential arc.
+ void fillByEdge(bool theTransversal);
FeaturePtr createArcFeature();
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_MacroEllipse.cpp
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#include <SketchPlugin_MacroEllipse.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_MacroArcReentrantMessage.h>
+#include <SketchPlugin_Point.h>
#include <SketchPlugin_Tools.h>
#include <SketchPlugin_Sketch.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeRefAttr.h>
-#include <ModelAPI_EventReentrantMessage.h>
+#include <ModelAPI_AttributeString.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Events.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_Ellipse2d.h>
#include <GeomAPI_Vertex.h>
void SketchPlugin_MacroEllipse::initAttributes()
{
+ data()->addAttribute(ELLIPSE_TYPE(), ModelAPI_AttributeString::typeId());
+ data()->addAttribute(EDIT_ELLIPSE_TYPE(), ModelAPI_AttributeString::typeId());
+
data()->addAttribute(CENTER_POINT_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(CENTER_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(PASSED_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(MAJOR_AXIS_START_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_START_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(MAJOR_AXIS_END_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_END_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(PASSED_POINT_1_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(PASSED_POINT_1_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+
data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
+ string(EDIT_ELLIPSE_TYPE())->setValue("");
+
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_POINT_REF_ID());
- ModelAPI_Session::get()->validators()->
- registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(
+ getKind(), MAJOR_AXIS_POINT_REF_ID());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(
+ getKind(), MAJOR_AXIS_START_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), MAJOR_AXIS_END_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PASSED_POINT_1_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EDIT_ELLIPSE_TYPE());
}
void SketchPlugin_MacroEllipse::execute()
{
FeaturePtr anEllipse = createEllipseFeature();
- constraintsForEllipse(anEllipse);
+
+ std::string aType = string(ELLIPSE_TYPE())->value();
+ if (aType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT())
+ constraintsForEllipseByCenterAxisAndPassed(anEllipse);
+ else if (aType == ELLIPSE_TYPE_BY_AXIS_AND_POINT())
+ constraintsForEllipseByMajoxAxisAndPassed(anEllipse);
// message to init reentrant operation
- static Events_ID anId = ModelAPI_EventReentrantMessage::eventId();
- ReentrantMessagePtr aMessage(new ModelAPI_EventReentrantMessage(anId, this));
+ static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+ <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
+
+ std::string anEditType = string(EDIT_ELLIPSE_TYPE())->value();
+ aMessage->setTypeOfCreation(!anEditType.empty() ? anEditType : aType);
aMessage->setCreatedFeature(anEllipse);
Events_Loop::loop()->send(aMessage);
}
void SketchPlugin_MacroEllipse::attributeChanged(const std::string& theID)
{
static const int NB_POINTS = 3;
- std::string aPointAttrName[NB_POINTS] = { CENTER_POINT_ID(),
- MAJOR_AXIS_POINT_ID(),
- PASSED_POINT_ID() };
- std::string aPointRefName[NB_POINTS] = { CENTER_POINT_REF_ID(),
- MAJOR_AXIS_POINT_REF_ID(),
- PASSED_POINT_REF_ID() };
-
- int aNbInitialized = 0;
- std::shared_ptr<GeomAPI_Pnt2d> anEllipsePoints[NB_POINTS];
-
- for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
- AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
- if (!aPointAttr->isInitialized())
- continue;
-
- AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
- // calculate ellipse parameters
- std::shared_ptr<GeomAPI_Pnt2d> aPassedPoint;
- std::shared_ptr<GeomAPI_Shape> aTangentCurve;
- SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
- aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+ std::string aPointAttrName[NB_POINTS];
+ std::string aPointRefName[NB_POINTS];
+ if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT()) {
+ aPointAttrName[0] = CENTER_POINT_ID();
+ aPointAttrName[1] = MAJOR_AXIS_POINT_ID();
+ aPointAttrName[2] = PASSED_POINT_ID();
+ aPointRefName[0] = CENTER_POINT_REF_ID();
+ aPointRefName[1] = MAJOR_AXIS_POINT_REF_ID();
+ aPointRefName[2] = PASSED_POINT_REF_ID();
+ } else if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+ aPointAttrName[0] = MAJOR_AXIS_START_ID();
+ aPointAttrName[1] = MAJOR_AXIS_END_ID();
+ aPointAttrName[2] = PASSED_POINT_1_ID();
+ aPointRefName[0] = MAJOR_AXIS_START_REF_ID();
+ aPointRefName[1] = MAJOR_AXIS_END_REF_ID();
+ aPointRefName[2] = PASSED_POINT_1_REF_ID();
+ }
+ else
+ return;
- anEllipsePoints[aNbInitialized++] = aPassedPoint;
+ // type of ellipse switched, thus reset all attributes
+ if (theID == ELLIPSE_TYPE()) {
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ SketchPlugin_Tools::resetAttribute(this, aPointAttrName[aPntIndex]);
+ SketchPlugin_Tools::resetAttribute(this, aPointRefName[aPntIndex]);
+ }
}
+ else {
+ int aNbInitialized = 0;
+ GeomPnt2dPtr anEllipsePoints[NB_POINTS];
+
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+ if (!aPointAttr->isInitialized())
+ continue;
+
+ AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+ // calculate ellipse parameters
+ GeomPnt2dPtr aPassedPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointAttr)->pnt();
+ GeomShapePtr aTangentCurve;
+ SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+ aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+
+ anEllipsePoints[aNbInitialized++] = aPassedPoint;
+ }
- std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
- if (aNbInitialized == 2) {
- std::shared_ptr<GeomAPI_Dir2d> aXDir(new GeomAPI_Dir2d(
- anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
- anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
- double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
- anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
- new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
- } else if (aNbInitialized == 3) {
- anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ if (aNbInitialized <= 1)
+ return; // too few points for the ellipse
+
+ if (string(ELLIPSE_TYPE())->value() == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+ // ellipse is given by major axis and passing point,
+ // recalculate the first point to be a center
+ anEllipsePoints[0]->setX(0.5 * (anEllipsePoints[0]->x() + anEllipsePoints[1]->x()));
+ anEllipsePoints[0]->setY(0.5 * (anEllipsePoints[0]->y() + anEllipsePoints[1]->y()));
+ }
+
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+ if (aNbInitialized == 2) {
+ GeomDir2dPtr aXDir(new GeomAPI_Dir2d(anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+ anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+ double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+ }
+ else if (aNbInitialized == 3) {
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
- }
+ }
- if (!anEllipse || anEllipse->implPtr<void>() == 0)
- return;
+ if (!anEllipse || anEllipse->implPtr<void>() == 0)
+ return;
- myCenter = anEllipse->center();
- myFocus = anEllipse->firstFocus();
- myMajorRadius = anEllipse->majorRadius();
- myMinorRadius = anEllipse->minorRadius();
+ myCenter = anEllipse->center();
+ myFocus = anEllipse->firstFocus();
+ myMajorRadius = anEllipse->majorRadius();
+ myMinorRadius = anEllipse->minorRadius();
- AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
- AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
+ AttributeDoublePtr aMajorRadiusAttr = real(MAJOR_RADIUS_ID());
+ AttributeDoublePtr aMinorRadiusAttr = real(MINOR_RADIUS_ID());
- bool aWasBlocked = data()->blockSendAttributeUpdated(true);
- // center attribute is used in processEvent() to set reference to reentrant arc
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(CENTER_POINT_ID()))->setValue(myCenter);
- aMajorRadiusAttr->setValue(myMajorRadius);
- aMinorRadiusAttr->setValue(myMinorRadius);
- data()->blockSendAttributeUpdated(aWasBlocked, false);
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ aMajorRadiusAttr->setValue(myMajorRadius);
+ aMinorRadiusAttr->setValue(myMinorRadius);
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+ }
}
+// LCOV_EXCL_START
std::string SketchPlugin_MacroEllipse::processEvent(
const std::shared_ptr<Events_Message>& theMessage)
{
std::string aFilledAttributeName;
- ReentrantMessagePtr aReentrantMessage =
- std::dynamic_pointer_cast<ModelAPI_EventReentrantMessage>(theMessage);
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+ std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
if (aReentrantMessage) {
FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+ std::string anEllipseType = aReentrantMessage->typeOfCreation();
+
+ string(ELLIPSE_TYPE())->setValue(anEllipseType);
+
+ aFilledAttributeName = ELLIPSE_TYPE();
ObjectPtr anObject = aReentrantMessage->selectedObject();
AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
if (aClickedPoint && (anObject || anAttribute)) {
aFilledAttributeName = CENTER_POINT_ID();
std::string aReferenceAttributeName = CENTER_POINT_REF_ID();
+ if (anEllipseType == ELLIPSE_TYPE_BY_AXIS_AND_POINT()) {
+ aFilledAttributeName = MAJOR_AXIS_START_ID();
+ aReferenceAttributeName = MAJOR_AXIS_START_REF_ID();
+ }
// fill 2d point attribute
AttributePoint2DPtr aPointAttr =
if (anAttribute) {
if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
if (aCreatedFeature && anAttribute->id() == CENTER_POINT_ID())
- anAttribute = aCreatedFeature->attribute(SketchPlugin_Ellipse::CENTER_ID());
+ anAttribute = aCreatedFeature->attribute(
+ anEllipseType == ELLIPSE_TYPE_BY_CENTER_AXIS_POINT() ?
+ SketchPlugin_Ellipse::CENTER_ID() :
+ SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
}
aRefAttr->setAttr(anAttribute);
}
else if (anObject.get()) {
- // if presentation of previous reentrant macro arc is used, the object is invalid,
- // we should use result of previous feature of the message(Arc)
- if (!anObject->data()->isValid())
- anObject = aCreatedFeature->lastResult();
- aRefAttr->setObject(anObject);
+ // if attribute is NULL, only object is defined, it should be processed outside
+ // the feature because it might be an external feature, that will be
+ // removed/created again after restart operation
+ // #2468 - Crash when sketching circles successively on a repetition
+ aFilledAttributeName = ELLIPSE_TYPE();
}
}
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
}
return aFilledAttributeName;
}
+// LCOV_EXCL_STOP
-void SketchPlugin_MacroEllipse::constraintsForEllipse(FeaturePtr theEllipseFeature)
+void SketchPlugin_MacroEllipse::constraintsForEllipseByCenterAxisAndPassed(
+ FeaturePtr theEllipseFeature)
{
+ // tangency on-the-fly is not applicable for ellipses
+ static const bool isTangencyApplicable = false;
// Create constraints.
SketchPlugin_Tools::createCoincidenceOrTangency(
this, CENTER_POINT_REF_ID(),
theEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
- ObjectPtr(), false);
+ ObjectPtr(), isTangencyApplicable);
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, MAJOR_AXIS_POINT_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ ObjectPtr(), isTangencyApplicable);
+ // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+ if (!refattr(PASSED_POINT_REF_ID())->isObject()) {
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, PASSED_POINT_REF_ID(), AttributePtr(),
+ theEllipseFeature->lastResult(), isTangencyApplicable);
+ }
+}
+
+void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed(
+ FeaturePtr theEllipseFeature)
+{
+ // tangency on-the-fly is not applicable for ellipses
+ static const bool isTangencyApplicable = false;
+ // Create constraints.
SketchPlugin_Tools::createCoincidenceOrTangency(
- this, MAJOR_AXIS_POINT_REF_ID(), AttributePtr(),
- theEllipseFeature->lastResult(), true);
+ this, MAJOR_AXIS_START_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+ ObjectPtr(), isTangencyApplicable);
SketchPlugin_Tools::createCoincidenceOrTangency(
- this, PASSED_POINT_REF_ID(), AttributePtr(),
- theEllipseFeature->lastResult(), true);
+ this, MAJOR_AXIS_END_REF_ID(),
+ theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ ObjectPtr(), isTangencyApplicable);
+ // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+ if (!refattr(PASSED_POINT_1_REF_ID())->isObject()) {
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, PASSED_POINT_1_REF_ID(), AttributePtr(),
+ theEllipseFeature->lastResult(), isTangencyApplicable);
+ }
}
FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature()
aCenterAttr->setValue(myCenter->x(), myCenter->y());
AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aEllipseFeature->attribute(SketchPlugin_Ellipse::FOCUS_ID()));
+ aEllipseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
aFocusAttr->setValue(myFocus->x(), myFocus->y());
aEllipseFeature->real(SketchPlugin_Ellipse::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
boolean(AUXILIARY_ID())->value());
aEllipseFeature->execute();
+
+ // create auxiliary points
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::CENTER_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::FIRST_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::SECOND_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
+ // create auxiliary axes
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+ SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(),
+ SketchPlugin_Ellipse::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+ SketchPlugin_Ellipse::MINOR_AXIS_START_ID(),
+ SketchPlugin_Ellipse::MINOR_AXIS_END_ID());
+
return aEllipseFeature;
}
aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
// Compute a ellipse in 3D view.
- std::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
- std::shared_ptr<GeomAPI_Pnt> aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
- std::shared_ptr<GeomAPI_Dir> aNormal = aNDir->dir();
- std::shared_ptr<GeomAPI_Dir> aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
+ GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ GeomPointPtr aFocus(aSketch->to3D(myFocus->x(), myFocus->y()));
+ GeomDirPtr aNormal = aNDir->dir();
+ GeomDirPtr aMajorAxis(new GeomAPI_Dir(aFocus->x() - aCenter->x(),
aFocus->y() - aCenter->y(), aFocus->z() - aCenter->z()));
std::shared_ptr<GeomAPI_Shape> anEllipseShape =
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
-// File: SketchPlugin_MacroEllipse.h
-// Created: 26 April 2017
-// Author: Artem ZHIDKOV
-
#ifndef SketchPlugin_MacroEllipse_H_
#define SketchPlugin_MacroEllipse_H_
#include <SketchPlugin_SketchEntity.h>
#include <GeomAPI_IPresentable.h>
-////class GeomAPI_Circ2d;
class GeomAPI_Pnt2d;
/**\class SketchPlugin_MacroEllipse
return ID;
}
- /// 2D point - center of the ellipse.
+ static const std::string& ELLIPSE_TYPE()
+ {
+ static const std::string ID("ellipse_type");
+ return ID;
+ }
+
+ static const std::string& ELLIPSE_TYPE_BY_CENTER_AXIS_POINT()
+ {
+ static const std::string ID("by_center_axis_point");
+ return ID;
+ }
+ static const std::string& ELLIPSE_TYPE_BY_AXIS_AND_POINT()
+ {
+ static const std::string ID("by_major_axis_and_point");
+ return ID;
+ }
+
+ static const std::string& EDIT_ELLIPSE_TYPE()
+ {
+ static const std::string ID("edit_ellipse_type");
+ return ID;
+ }
+
+ /// Attribute for the first point selected during ellipse creation.
inline static const std::string& CENTER_POINT_ID()
{
- static const std::string ID("center_point");
+ static const std::string ID("first_point");
return ID;
}
- /// Reference for center point selection.
+ /// Reference to the first selected point.
inline static const std::string& CENTER_POINT_REF_ID()
{
- static const std::string ID("center_point_ref");
+ static const std::string ID("first_point_ref");
return ID;
}
- /// 2D point - major axis point of the ellipse.
+ /// Attribute for the second point selected during ellipse creation.
inline static const std::string& MAJOR_AXIS_POINT_ID()
{
- static const std::string ID("major_axis_point");
+ static const std::string ID("second_point");
return ID;
}
- /// Reference for major axis point selection.
+ /// Reference to the second selected point.
inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
{
- static const std::string ID("major_axis_point_ref");
+ static const std::string ID("second_point_ref");
return ID;
}
- /// 2D point - passed point of the ellipse
+ /// Attribute for the third point selected during ellipse creation.
inline static const std::string& PASSED_POINT_ID()
{
static const std::string ID("passed_point");
return ID;
}
+ /// Attribute for the first point selected during ellipse creation.
+ inline static const std::string& MAJOR_AXIS_START_ID()
+ {
+ static const std::string ID("first_point_1");
+ return ID;
+ }
+
+ /// Reference to the first selected point.
+ inline static const std::string& MAJOR_AXIS_START_REF_ID()
+ {
+ static const std::string ID("first_point_ref_1");
+ return ID;
+ }
+
+ /// Attribute for the second point selected during ellipse creation.
+ inline static const std::string& MAJOR_AXIS_END_ID()
+ {
+ static const std::string ID("second_point_1");
+ return ID;
+ }
+
+ /// Reference to the second selected point.
+ inline static const std::string& MAJOR_AXIS_END_REF_ID()
+ {
+ static const std::string ID("second_point_ref_1");
+ return ID;
+ }
+
+ /// Attribute for the third point selected during ellipse creation.
+ inline static const std::string& PASSED_POINT_1_ID()
+ {
+ static const std::string ID("passed_point_1");
+ return ID;
+ }
+
+ /// Reference for passed point selection.
+ inline static const std::string& PASSED_POINT_1_REF_ID()
+ {
+ static const std::string ID("passed_point_ref_1");
+ return ID;
+ }
+
/// Major radius of the ellipse
inline static const std::string& MAJOR_RADIUS_ID()
{
- static const std::string ID("ellipse_major_radius");
+ static const std::string ID("major_radius");
return ID;
}
/// Minor radius of the ellipse
inline static const std::string& MINOR_RADIUS_ID()
{
- static const std::string ID("ellipse_minor_radius");
+ static const std::string ID("minor_radius");
return ID;
}
SketchPlugin_MacroEllipse();
private:
- void constraintsForEllipse(FeaturePtr theEllipseFeature);
+ void constraintsForEllipseByCenterAxisAndPassed(FeaturePtr theEllipseFeature);
+ void constraintsForEllipseByMajoxAxisAndPassed(FeaturePtr theEllipseFeature);
FeaturePtr createEllipseFeature();
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <SketchPlugin_MacroEllipticArc.h>
+
+#include <SketchPlugin_EllipticArc.h>
+#include <SketchPlugin_MacroArcReentrantMessage.h>
+#include <SketchPlugin_Tools.h>
+#include <SketchPlugin_Sketch.h>
+
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+#include <ModelAPI_Events.h>
+
+#include <GeomDataAPI_Point2D.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Vertex.h>
+
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_PointBuilder.h>
+
+
+const double paramTolerance = 1.e-4;
+const double PI = 3.141592653589793238463;
+
+
+SketchPlugin_MacroEllipticArc::SketchPlugin_MacroEllipticArc()
+ : SketchPlugin_SketchEntity(),
+ myMajorRadius(0.0),
+ myMinorRadius(0.0),
+ myParamDelta(0.0)
+{
+}
+
+void SketchPlugin_MacroEllipticArc::initAttributes()
+{
+ data()->addAttribute(CENTER_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(CENTER_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(MAJOR_AXIS_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(MAJOR_AXIS_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(START_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(START_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+ data()->addAttribute(END_POINT_ID(), GeomDataAPI_Point2D::typeId());
+ data()->addAttribute(END_POINT_REF_ID(), ModelAPI_AttributeRefAttr::typeId());
+
+ data()->addAttribute(MAJOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+ data()->addAttribute(MINOR_RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
+
+ data()->addAttribute(REVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
+ data()->addAttribute(AUXILIARY_ID(), ModelAPI_AttributeBoolean::typeId());
+
+ boolean(REVERSED_ID())->setValue(false);
+
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), CENTER_REF_ID());
+ ModelAPI_Session::get()->validators()
+ ->registerNotObligatory(getKind(), MAJOR_AXIS_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), START_POINT_REF_ID());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), END_POINT_REF_ID());
+}
+
+void SketchPlugin_MacroEllipticArc::execute()
+{
+ FeaturePtr anEllipse = createEllipticArcFeature();
+ constraintsForEllipticArc(anEllipse);
+
+ // message to init reentrant operation
+ static Events_ID anId = SketchPlugin_MacroArcReentrantMessage::eventId();
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aMessage = std::shared_ptr
+ <SketchPlugin_MacroArcReentrantMessage>(new SketchPlugin_MacroArcReentrantMessage(anId, this));
+ aMessage->setCreatedFeature(anEllipse);
+ Events_Loop::loop()->send(aMessage);
+}
+
+void SketchPlugin_MacroEllipticArc::attributeChanged(const std::string& theID)
+{
+ static const int NB_POINTS = 4;
+ std::string aPointAttrName[NB_POINTS] = { CENTER_ID(),
+ MAJOR_AXIS_POINT_ID(),
+ START_POINT_ID(),
+ END_POINT_ID() };
+ std::string aPointRefName[NB_POINTS] = { CENTER_REF_ID(),
+ MAJOR_AXIS_POINT_REF_ID(),
+ START_POINT_REF_ID(),
+ END_POINT_REF_ID() };
+
+ int aNbInitialized = 0;
+ GeomPnt2dPtr anEllipsePoints[NB_POINTS];
+
+ for (int aPntIndex = 0; aPntIndex < NB_POINTS; ++aPntIndex) {
+ AttributePtr aPointAttr = attribute(aPointAttrName[aPntIndex]);
+ if (!aPointAttr->isInitialized())
+ continue;
+
+ AttributeRefAttrPtr aPointRef = refattr(aPointRefName[aPntIndex]);
+ // calculate ellipse parameters
+ GeomPnt2dPtr aPassedPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointAttr)->pnt();
+ GeomShapePtr aTangentCurve;
+ SketchPlugin_Tools::convertRefAttrToPointOrTangentCurve(
+ aPointRef, aPointAttr, aTangentCurve, aPassedPoint);
+
+ anEllipsePoints[aNbInitialized++] = aPassedPoint;
+ }
+
+ if (aNbInitialized <= 1)
+ return; // too few points for the ellipse
+
+ myCenter = anEllipsePoints[0];
+ myMajorAxis = anEllipsePoints[1];
+ myStartPnt = anEllipsePoints[2];
+ myEndPnt = anEllipsePoints[3];
+
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse;
+ if (aNbInitialized == 2) {
+ GeomDir2dPtr aXDir(new GeomAPI_Dir2d(anEllipsePoints[1]->x() - anEllipsePoints[0]->x(),
+ anEllipsePoints[1]->y() - anEllipsePoints[0]->y()));
+ double aMajorRad = anEllipsePoints[1]->distance(anEllipsePoints[0]);
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], aXDir, aMajorRad, 0.5 * aMajorRad));
+ }
+ else if (aNbInitialized >= 3) {
+ anEllipse = std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(anEllipsePoints[0], anEllipsePoints[1], anEllipsePoints[2]));
+ }
+
+ if (!anEllipse || anEllipse->implPtr<void>() == 0)
+ return;
+
+ myMajorRadius = anEllipse->majorRadius();
+ myMinorRadius = anEllipse->minorRadius();
+
+ bool aWasBlocked = data()->blockSendAttributeUpdated(true);
+ real(MAJOR_RADIUS_ID())->setValue(myMajorRadius);
+ real(MINOR_RADIUS_ID())->setValue(myMinorRadius);
+ data()->blockSendAttributeUpdated(aWasBlocked, false);
+
+ // update the REVERSED flag
+ if (myEndPnt) {
+ double aParameterEnd = 0.0;
+ GeomPnt2dPtr aEnd = anEllipse->project(myEndPnt);
+ if (anEllipse->parameter(aEnd, paramTolerance, aParameterEnd)) {
+ double aParamStart = 0.0;
+ anEllipse->parameter(myStartPnt, paramTolerance, aParamStart);
+ aParameterEnd -= aParamStart;
+
+ if (myParamDelta > 0.0 && myParamDelta <= PI * 0.5 &&
+ aParameterEnd < 0 && aParameterEnd >= -PI * 0.5) {
+ boolean(REVERSED_ID())->setValue(true);
+ }
+ else if (myParamDelta < 0.0 && myParamDelta >= -PI * 0.5 &&
+ aParameterEnd > 0.0 && aParameterEnd <= PI * 0.5) {
+ boolean(REVERSED_ID())->setValue(false);
+ }
+ }
+ myParamDelta = aParameterEnd;
+ }
+}
+
+// LCOV_EXCL_START
+std::string SketchPlugin_MacroEllipticArc::processEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ std::string aFilledAttributeName;
+
+ std::shared_ptr<SketchPlugin_MacroArcReentrantMessage> aReentrantMessage =
+ std::dynamic_pointer_cast<SketchPlugin_MacroArcReentrantMessage>(theMessage);
+ if (aReentrantMessage) {
+ FeaturePtr aCreatedFeature = aReentrantMessage->createdFeature();
+
+ ObjectPtr anObject = aReentrantMessage->selectedObject();
+ AttributePtr anAttribute = aReentrantMessage->selectedAttribute();
+ std::shared_ptr<GeomAPI_Pnt2d> aClickedPoint = aReentrantMessage->clickedPoint();
+
+ if (aClickedPoint && (anObject || anAttribute)) {
+ aFilledAttributeName = CENTER_ID();
+ std::string aReferenceAttributeName = CENTER_REF_ID();
+
+ // fill 2d point attribute
+ AttributePoint2DPtr aPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(attribute(aFilledAttributeName));
+ aPointAttr->setValue(aClickedPoint);
+
+ // fill reference attribute
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(attribute(aReferenceAttributeName));
+ if (anAttribute) {
+ if (!anAttribute->owner() || !anAttribute->owner()->data()->isValid()) {
+ if (aCreatedFeature && anAttribute->id() == CENTER_ID())
+ anAttribute = aCreatedFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID());
+ }
+ aRefAttr->setAttr(anAttribute);
+ }
+ else if (anObject.get()) {
+ // if attribute is NULL, only object is defined, it should be processed outside
+ // the feature because it might be an external feature, that will be
+ // removed/created again after restart operation
+ // #2468 - Crash when sketching circles successively on a repetition
+ aFilledAttributeName = "";
+ }
+ }
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+ }
+ return aFilledAttributeName;
+}
+// LCOV_EXCL_STOP
+
+FeaturePtr SketchPlugin_MacroEllipticArc::createEllipticArcFeature()
+{
+ GeomShapePtr anArc = getArcShape();
+ GeomEllipsePtr anEllipse;
+ GeomPointPtr aStartPoint, aEndPoint;
+ if (anArc->isEdge()) {
+ GeomEdgePtr anArcEdge = anArc->edge();
+ aStartPoint = anArcEdge->firstPoint();
+ aEndPoint = anArcEdge->lastPoint();
+ if (boolean(REVERSED_ID())->value())
+ std::swap(aStartPoint, aEndPoint);
+
+ if (anArcEdge->isEllipse())
+ anEllipse = anArcEdge->ellipse();
+ }
+
+ if (!anEllipse)
+ return FeaturePtr();
+
+ // Create and fill new EllipticArc feature
+ SketchPlugin_Sketch* aSketch = sketch();
+ FeaturePtr aEllipseFeature = aSketch->addFeature(SketchPlugin_EllipticArc::ID());
+
+ AttributePoint2DPtr aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
+ aCenterAttr->setValue(aSketch->to2D(anEllipse->center()));
+
+ AttributePoint2DPtr aFocusAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()));
+ aFocusAttr->setValue(aSketch->to2D(anEllipse->firstFocus()));
+
+ AttributePoint2DPtr aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ aStartAttr->setValue(aSketch->to2D(aStartPoint));
+
+ AttributePoint2DPtr aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aEllipseFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ aEndAttr->setValue(aSketch->to2D(aEndPoint));
+
+ aEllipseFeature->real(SketchPlugin_EllipticArc::MAJOR_RADIUS_ID())->setValue(myMajorRadius);
+ aEllipseFeature->real(SketchPlugin_EllipticArc::MINOR_RADIUS_ID())->setValue(myMinorRadius);
+
+ aEllipseFeature->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(
+ boolean(REVERSED_ID())->value());
+
+ aEllipseFeature->boolean(SketchPlugin_EllipticArc::AUXILIARY_ID())->setValue(
+ boolean(AUXILIARY_ID())->value());
+
+ aEllipseFeature->execute();
+
+ // create auxiliary points
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::CENTER_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::FIRST_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::SECOND_FOCUS_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MINOR_AXIS_START_ID());
+ SketchPlugin_Tools::createAuxiliaryPointOnEllipse(
+ aEllipseFeature, SketchPlugin_EllipticArc::MINOR_AXIS_END_ID());
+ // create auxiliary axes
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+ SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID());
+ SketchPlugin_Tools::createAuxiliaryAxisOfEllipse(aEllipseFeature,
+ SketchPlugin_EllipticArc::MINOR_AXIS_START_ID(),
+ SketchPlugin_EllipticArc::MINOR_AXIS_END_ID());
+
+ return aEllipseFeature;
+}
+
+void SketchPlugin_MacroEllipticArc::constraintsForEllipticArc(FeaturePtr theEllipticArc)
+{
+ // tangency on-the-fly is not applicable for elliptic arcs
+ static const bool isTangencyApplicable = false;
+ // Create constraints.
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, CENTER_REF_ID(),
+ theEllipticArc->attribute(SketchPlugin_EllipticArc::CENTER_ID()),
+ ObjectPtr(), isTangencyApplicable);
+ // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object
+ if (!refattr(MAJOR_AXIS_POINT_REF_ID())->isObject()) {
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, MAJOR_AXIS_POINT_REF_ID(),
+ AttributePtr(),
+ theEllipticArc->lastResult(), isTangencyApplicable);
+ }
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, START_POINT_REF_ID(),
+ theEllipticArc->attribute(SketchPlugin_EllipticArc::START_POINT_ID()),
+ ObjectPtr(), isTangencyApplicable);
+ SketchPlugin_Tools::createCoincidenceOrTangency(
+ this, END_POINT_REF_ID(),
+ theEllipticArc->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ ObjectPtr(), isTangencyApplicable);
+}
+
+AISObjectPtr SketchPlugin_MacroEllipticArc::getAISObject(AISObjectPtr thePrevious)
+{
+ SketchPlugin_Sketch* aSketch = sketch();
+ if (!aSketch || !myCenter || !myMajorAxis)
+ return AISObjectPtr();
+
+ // Compute a elliptic arc in 3D view.
+ GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ GeomShapePtr aCenterPointShape = GeomAlgoAPI_PointBuilder::vertex(aCenter);
+ GeomShapePtr anArcShape = getArcShape();
+ if (!anArcShape.get() || !aCenterPointShape.get())
+ return AISObjectPtr();
+
+ std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+ aShapes.push_back(anArcShape);
+ aShapes.push_back(aCenterPointShape);
+
+ std::shared_ptr<GeomAPI_Shape> aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+ AISObjectPtr anAIS = thePrevious;
+ if (!anAIS)
+ anAIS.reset(new GeomAPI_AISObject());
+ anAIS->createShape(aCompound);
+ return anAIS;
+}
+
+GeomShapePtr SketchPlugin_MacroEllipticArc::getArcShape()
+{
+ if (!myCenter.get() || !myMajorAxis.get())
+ return GeomShapePtr();
+
+ SketchPlugin_Sketch* aSketch = sketch();
+ if (!aSketch)
+ return GeomShapePtr();
+
+ GeomPointPtr aCenter(aSketch->to3D(myCenter->x(), myCenter->y()));
+ GeomPointPtr aMajorAxisPnt(aSketch->to3D(myMajorAxis->x(), myMajorAxis->y()));
+ GeomDirPtr aMajorAxisDir(new GeomAPI_Dir(aMajorAxisPnt->x() - aCenter->x(),
+ aMajorAxisPnt->y() - aCenter->y(),
+ aMajorAxisPnt->z() - aCenter->z()));
+
+ std::shared_ptr<GeomDataAPI_Dir> aNDir = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aSketch->attribute(SketchPlugin_Sketch::NORM_ID()));
+ GeomDirPtr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
+
+ GeomPointPtr aStart, anEnd;
+ if (myStartPnt)
+ aStart = aSketch->to3D(myStartPnt->x(), myStartPnt->y());
+ if (myEndPnt)
+ anEnd = aSketch->to3D(myEndPnt->x(), myEndPnt->y());
+
+ GeomShapePtr anArcShape;
+ if (anEnd) {
+ if (boolean(REVERSED_ID())->value())
+ std::swap(aStart, anEnd);
+
+ anArcShape = GeomAlgoAPI_EdgeBuilder::ellipticArc(aCenter, aNormal, aMajorAxisDir,
+ myMajorRadius, myMinorRadius, aStart, anEnd);
+ }
+ else {
+ anArcShape = GeomAlgoAPI_EdgeBuilder::ellipse(aCenter, aNormal, aMajorAxisDir,
+ myMajorRadius, myMinorRadius);
+ }
+
+ return anArcShape;
+}
--- /dev/null
+// Copyright (C) 2017-2019 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SketchPlugin_MacroEllipticArc_H_
+#define SketchPlugin_MacroEllipticArc_H_
+
+#include <ModelAPI_IReentrant.h>
+#include <SketchPlugin.h>
+#include <SketchPlugin_SketchEntity.h>
+#include <GeomAPI_IPresentable.h>
+
+class GeomAPI_Pnt2d;
+class GeomAPI_Shape;
+
+/**\class SketchPlugin_MacroEllipticArc
+ * \ingroup Plugins
+ * \brief Feature for creation of the new elliptic arc in Sketch.
+ */
+class SketchPlugin_MacroEllipticArc: public SketchPlugin_SketchEntity,
+ public GeomAPI_IPresentable,
+ public ModelAPI_IReentrant
+{
+public:
+ /// Elliptic arc feature kind
+ inline static const std::string& ID()
+ {
+ static const std::string ID("SketchMacroEllipticArc");
+ return ID;
+ }
+
+ /// Attribute for the central point selected during elliptic arc creation.
+ inline static const std::string& CENTER_ID()
+ {
+ static const std::string ID("center");
+ return ID;
+ }
+
+ /// Reference to the first selected point (center of ellipse).
+ inline static const std::string& CENTER_REF_ID()
+ {
+ static const std::string ID("center_ref");
+ return ID;
+ }
+
+ /// Attribute for the point on major semi-axis selected during elliptic arc creation.
+ inline static const std::string& MAJOR_AXIS_POINT_ID()
+ {
+ static const std::string ID("major_axis_point");
+ return ID;
+ }
+
+ /// Reference to the second selected point (major semi-axis of the ellipse).
+ inline static const std::string& MAJOR_AXIS_POINT_REF_ID()
+ {
+ static const std::string ID("major_axis_point_ref");
+ return ID;
+ }
+
+ /// Attribute for the start point of the elliptic arc selected during creation.
+ inline static const std::string& START_POINT_ID()
+ {
+ static const std::string ID("start_point");
+ return ID;
+ }
+
+ /// Reference for the start point selection.
+ inline static const std::string& START_POINT_REF_ID()
+ {
+ static const std::string ID("start_point_ref");
+ return ID;
+ }
+
+ /// Attribute for the end point of the elliptic arc selected during creation.
+ inline static const std::string& END_POINT_ID()
+ {
+ static const std::string ID("end_point");
+ return ID;
+ }
+
+ /// Reference for the end point selection.
+ inline static const std::string& END_POINT_REF_ID()
+ {
+ static const std::string ID("end_point_ref");
+ return ID;
+ }
+
+ /// Major radius of the ellipse
+ inline static const std::string& MAJOR_RADIUS_ID()
+ {
+ static const std::string ID("major_radius");
+ return ID;
+ }
+
+ /// Minor radius of the ellipse
+ inline static const std::string& MINOR_RADIUS_ID()
+ {
+ static const std::string ID("minor_radius");
+ return ID;
+ }
+
+ /// Flag the arc is reversed
+ inline static const std::string& REVERSED_ID()
+ {
+ static const std::string ID("reversed");
+ return ID;
+ }
+
+ /// Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_MacroEllipticArc::ID();
+ return MY_KIND;
+ }
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes.
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Returns the AIS preview
+ virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// Reimplemented from ModelAPI_Feature::isMacro().
+ /// \returns true
+ SKETCHPLUGIN_EXPORT virtual bool isMacro() const
+ {return true;}
+
+ SKETCHPLUGIN_EXPORT virtual bool isPreviewNeeded() const
+ {return false;}
+
+ /// Apply information of the message to current object. It fills reference object,
+ /// tangent type and tangent point refence in case of tangent arc
+ virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ /// Use plugin manager for features creation
+ SketchPlugin_MacroEllipticArc();
+
+private:
+ std::shared_ptr<GeomAPI_Shape> getArcShape();
+
+ FeaturePtr createEllipticArcFeature();
+ void constraintsForEllipticArc(FeaturePtr theEllipticArc);
+
+private:
+ std::shared_ptr<GeomAPI_Pnt2d> myCenter;
+ std::shared_ptr<GeomAPI_Pnt2d> myMajorAxis;
+ std::shared_ptr<GeomAPI_Pnt2d> myStartPnt;
+ std::shared_ptr<GeomAPI_Pnt2d> myEndPnt;
+ double myMajorRadius;
+ double myMinorRadius;
+ double myParamDelta;
+};
+
+#endif
#include <SketchPlugin_Projection.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintDistance.h>
#include <SketchPlugin_ConstraintDistanceHorizontal.h>
#include <SketchPlugin_ExternalValidator.h>
#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_MacroEllipse.h>
+#include <SketchPlugin_EllipticArc.h>
+#include <SketchPlugin_MacroEllipticArc.h>
#include <SketchPlugin_SketchDrawer.h>
#include <SketcherPrs_Tools.h>
new SketchPlugin_ExternalValidator);
aFactory->registerValidator("SketchPlugin_TangentAttr",
new SketchPlugin_TangentAttrValidator);
+ aFactory->registerValidator("SketchPlugin_PerpendicularAttr",
+ new SketchPlugin_PerpendicularAttrValidator);
aFactory->registerValidator("SketchPlugin_NotFixed",
new SketchPlugin_NotFixedValidator);
aFactory->registerValidator("SketchPlugin_EqualAttr",
new SketchPlugin_MiddlePointAttrValidator);
aFactory->registerValidator("SketchPlugin_ArcTangentPoint",
new SketchPlugin_ArcTangentPointValidator);
+ aFactory->registerValidator("SketchPlugin_ArcTransversalPoint",
+ new SketchPlugin_ArcTransversalPointValidator);
aFactory->registerValidator("SketchPlugin_IntersectionValidator",
new SketchPlugin_IntersectionValidator);
aFactory->registerValidator("SketchPlugin_ProjectionValidator",
return FeaturePtr(new SketchPlugin_Projection);
} else if (theFeatureID == SketchPlugin_ConstraintCoincidence::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintCoincidence);
+ } else if (theFeatureID == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
+ return FeaturePtr(new SketchPlugin_ConstraintCoincidenceInternal);
} else if (theFeatureID == SketchPlugin_ConstraintCollinear::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintCollinear);
} else if (theFeatureID == SketchPlugin_ConstraintDistance::ID()) {
return FeaturePtr(new SketchPlugin_Ellipse);
} else if (theFeatureID == SketchPlugin_MacroEllipse::ID()) {
return FeaturePtr(new SketchPlugin_MacroEllipse);
+ } else if (theFeatureID == SketchPlugin_EllipticArc::ID()) {
+ return FeaturePtr(new SketchPlugin_EllipticArc);
+ } else if (theFeatureID == SketchPlugin_MacroEllipticArc::ID()) {
+ return FeaturePtr(new SketchPlugin_MacroEllipticArc);
} else if (theFeatureID == SketchPlugin_SketchDrawer::ID()) {
return FeaturePtr(new SketchPlugin_SketchDrawer);
}
aMsg->setState(SketchPlugin_Circle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Arc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Ellipse::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_EllipticArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Projection::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCoincidence::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_ConstraintCoincidenceInternal::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintCollinear::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistance::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintLength::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_Trim::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MacroCircle::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_MacroEllipse::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_MacroEllipticArc::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistanceHorizontal::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintDistanceVertical::ID(), aHasSketchPlane);
// SketchRectangle is a python feature, so its ID is passed just as a string
#include <ModelAPI_Data.h>
#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_AttributeReference.h>
#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_Session.h>
data()->addAttribute(SketchPlugin_Point::COORD_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
+
+ data()->addAttribute(PARENT_ID(), ModelAPI_AttributeReference::typeId());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PARENT_ID());
}
void SketchPlugin_Point::execute()
static const std::string MY_COORD_ID("PointCoordinates");
return MY_COORD_ID;
}
+ /// Reference to the parent feature
+ inline static const std::string& PARENT_ID()
+ {
+ static const std::string& MY_PARENT_ID("ParentFeature");
+ return MY_PARENT_ID;
+ }
/// Returns the kind of a feature
SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
{
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Sketch.h>
#include <GeomAPI_Circ.h>
#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_Vertex.h>
#include <GeomAlgoAPI_EdgeBuilder.h>
+#include <GeomAlgoAPI_Projection.h>
#include <GeomDataAPI_Point2D.h>
#include <cmath>
}
}
-static bool isValidProjectionType(FeaturePtr theProjection,
- GeomEdgePtr theEdge,
- GeomVertexPtr theVertex)
+static const std::set<std::string>& POINT_PROJECTION()
{
- if (theVertex && theProjection->getKind() == SketchPlugin_Point::ID())
- return true;
+ static std::set<std::string> aProj;
+ if (aProj.empty())
+ aProj.insert(SketchPlugin_Point::ID());
+ return aProj;
+}
+
+static const std::set<std::string>& LINE_PROJECTION()
+{
+ static std::set<std::string> aProj;
+ if (aProj.empty())
+ aProj.insert(SketchPlugin_Line::ID());
+ return aProj;
+}
+
+static const std::set<std::string>& CIRCLE_ELLIPSE_PROJECTION()
+{
+ static std::set<std::string> aProj;
+ if (aProj.empty()) {
+ aProj.insert(SketchPlugin_Circle::ID());
+ aProj.insert(SketchPlugin_Ellipse::ID());
+ }
+ return aProj;
+}
+
+static const std::set<std::string>& ARC_PROJECTION()
+{
+ static std::set<std::string> aProj;
+ if (aProj.empty()) {
+ aProj.insert(SketchPlugin_Arc::ID());
+ aProj.insert(SketchPlugin_EllipticArc::ID());
+ }
+ return aProj;
+}
+
+
+static const std::set<std::string>& possibleProjectionTypes(GeomEdgePtr theEdge,
+ GeomVertexPtr theVertex)
+{
+ if (theVertex)
+ return POINT_PROJECTION();
if (theEdge) {
- if (theEdge->isLine() && theProjection->getKind() == SketchPlugin_Line::ID())
- return true;
- else if (theEdge->isCircle() && theProjection->getKind() == SketchPlugin_Circle::ID())
- return true;
- else if (theEdge->isArc() && theProjection->getKind() == SketchPlugin_Arc::ID())
- return true;
+ if (theEdge->isLine())
+ return LINE_PROJECTION();
+ else if (theEdge->isCircle() || theEdge->isArc() || theEdge->isEllipse()) {
+ if (theEdge->isClosed())
+ return CIRCLE_ELLIPSE_PROJECTION();
+ else
+ return ARC_PROJECTION();
+ }
}
- return false;
+ static const std::set<std::string> DUMMY;
+ return DUMMY;
}
void SketchPlugin_Projection::computeProjection(const std::string& theID)
if (!anEdge && !aVertex)
return;
+ const std::set<std::string>& aProjType = possibleProjectionTypes(anEdge, aVertex);
+
AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
FeaturePtr aProjection;
if (aRefAttr && aRefAttr->isInitialized())
aProjection = ModelAPI_Feature::feature(aRefAttr->object());
// if the type of feature differs with already selected, remove it and create once again
- bool hasPrevProj = aProjection.get() != 0;
- if (hasPrevProj && !isValidProjectionType(aProjection, anEdge, aVertex)) {
- DocumentPtr aDoc = sketch()->document();
-
- aRefAttr->setObject(data()->owner()); // to not remove of this remove reference to aProjection
- std::set<FeaturePtr> aFeaturesToBeRemoved;
- aFeaturesToBeRemoved.insert(aProjection);
- ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
- aProjection = FeaturePtr();
- aRefAttr->setObject(aProjection);
- hasPrevProj = false;
- }
+ bool isRebuild = rebuildProjectedFeature(aProjection, aProjType);
std::shared_ptr<GeomAPI_Pln> aSketchPlane = sketch()->plane();
ResultConstructionPtr aResult =
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(lastResult());
- if (aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) {
+ if (!isRebuild && aResult && aResult->shape() && theID == EXTERNAL_FEATURE_ID()) {
aResult->setShape(std::shared_ptr<GeomAPI_Edge>());
if (aProjection)
aProjection->selection(EXTERNAL_ID())->setValue(lastResult(), lastResult()->shape());
std::shared_ptr<GeomAPI_Pnt> aPrjPnt = aSketchPlane->project(aVertex->point());
std::shared_ptr<GeomAPI_Pnt2d> aPntInSketch = sketch()->to2D(aPrjPnt);
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Point::ID());
+ rebuildProjectedFeature(aProjection, POINT_PROJECTION(), SketchPlugin_Point::ID());
// update coordinates of projection
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
if (aFirstInSketch->distance(aLastInSketch) < tolerance)
return; // line is semi-orthogonal to the sketch plane
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Line::ID());
+ rebuildProjectedFeature(aProjection, LINE_PROJECTION(), SketchPlugin_Line::ID());
// update attributes of projection
std::shared_ptr<GeomDataAPI_Point2D> aStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aStartPnt->setValue(aFirstInSketch);
aEndPnt->setValue(aLastInSketch);
}
- else if (anEdge->isCircle()) {
- std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
- double aRadius = aCircle->radius();
-
- double aNormalsDot = aCircle->normal()->dot(aSketchPlane->direction());
- if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
- return; // circle is not in the plane, parallel to the sketch plane
-
- std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
- std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
-
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Circle::ID());
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
- aCenterPnt->setValue(aCenterInSketch);
- aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aRadius);
- }
- else if (anEdge->isArc()) {
- std::shared_ptr<GeomAPI_Pnt> aFirst = aSketchPlane->project(anEdge->firstPoint());
- std::shared_ptr<GeomAPI_Pnt> aLast = aSketchPlane->project(anEdge->lastPoint());
- std::shared_ptr<GeomAPI_Pnt2d> aFirstInSketch = sketch()->to2D(aFirst);
- std::shared_ptr<GeomAPI_Pnt2d> aLastInSketch = sketch()->to2D(aLast);
-
- std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
- std::shared_ptr<GeomAPI_Pnt> aCenter = aSketchPlane->project(aCircle->center());
- std::shared_ptr<GeomAPI_Pnt2d> aCenterInSketch = sketch()->to2D(aCenter);
-
- double aNormalsDot = aCircle->normal()->dot(aSketchPlane->direction());
- if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
- return; // arc is not in the plane, parallel to the sketch plane
-
- bool isInversed = aNormalsDot < 0.;
-
- if (!hasPrevProj)
- aProjection = sketch()->addFeature(SketchPlugin_Arc::ID());
-
- bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
-
- // update attributes of projection
- std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Arc::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aProjection->attribute(SketchPlugin_Arc::END_ID()));
- aStartPnt->setValue(aFirstInSketch);
- aEndPnt->setValue(aLastInSketch);
- aCenterPnt->setValue(aCenterInSketch);
- aProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed);
-
- aProjection->data()->blockSendAttributeUpdated(aWasBlocked);
+ else if (anEdge->isCircle() || anEdge->isArc() || anEdge->isEllipse()) {
+ GeomAlgoAPI_Projection aProjAlgo(aSketchPlane);
+ GeomCurvePtr aProjectedCurve = aProjAlgo.project(anEdge);
+
+ if (aProjectedCurve->isCircle()) {
+ GeomAPI_Circ aCircle(aProjectedCurve);
+ GeomPointPtr aCenter = aSketchPlane->project(aCircle.center());
+ GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
+
+ if (aProjectedCurve->isTrimmed()) {
+ // ARC is a projection
+ rebuildProjectedFeature(aProjection, ARC_PROJECTION(), SketchPlugin_Arc::ID());
+
+ GeomPointPtr aFirst = aProjectedCurve->getPoint(aProjectedCurve->startParam());
+ GeomPointPtr aLast = aProjectedCurve->getPoint(aProjectedCurve->endParam());
+ GeomPnt2dPtr aFirstInSketch = sketch()->to2D(aSketchPlane->project(aFirst));
+ GeomPnt2dPtr aLastInSketch = sketch()->to2D(aSketchPlane->project(aLast));
+
+ double aNormalsDot = aCircle.normal()->dot(aSketchPlane->direction());
+ if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
+ return; // arc is not in the plane, parallel to the sketch plane
+
+ bool isInversed = aNormalsDot < 0.;
+
+ bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Arc::END_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+ aCenterPnt->setValue(aCenterInSketch);
+ aProjection->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(isInversed);
+
+ aProjection->data()->blockSendAttributeUpdated(aWasBlocked);
+ }
+ else {
+ // CIRCLE is a projection
+ rebuildProjectedFeature(aProjection, CIRCLE_ELLIPSE_PROJECTION(),
+ SketchPlugin_Circle::ID());
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Circle::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ aProjection->real(SketchPlugin_Circle::RADIUS_ID())->setValue(aCircle.radius());
+ }
+ }
+ else if (aProjectedCurve->isEllipse()) {
+ GeomAPI_Ellipse anEllipse(aProjectedCurve);
+ GeomPointPtr aCenter = aSketchPlane->project(anEllipse.center());
+ GeomPnt2dPtr aCenterInSketch = sketch()->to2D(aCenter);
+ GeomPointPtr aFocus = aSketchPlane->project(anEllipse.firstFocus());
+ GeomPnt2dPtr aFocusInSketch = sketch()->to2D(aFocus);
+
+ if (aProjectedCurve->isTrimmed()) {
+ // ELLIPTIC ARC is a projection
+ rebuildProjectedFeature(aProjection, ARC_PROJECTION(), SketchPlugin_EllipticArc::ID());
+
+ GeomPointPtr aFirst = aProjectedCurve->getPoint(aProjectedCurve->startParam());
+ GeomPointPtr aLast = aProjectedCurve->getPoint(aProjectedCurve->endParam());
+ GeomPnt2dPtr aFirstInSketch = sketch()->to2D(aSketchPlane->project(aFirst));
+ GeomPnt2dPtr aLastInSketch = sketch()->to2D(aSketchPlane->project(aLast));
+
+ double aNormalsDot = anEllipse.normal()->dot(aSketchPlane->direction());
+ if (fabs(fabs(aNormalsDot) - 1.0) > tolerance)
+ return; // arc is not in the plane, parallel to the sketch plane
+
+ bool isInversed = aNormalsDot < 0.;
+
+ bool aWasBlocked = aProjection->data()->blockSendAttributeUpdated(true);
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ aStartPnt->setValue(aFirstInSketch);
+ aEndPnt->setValue(aLastInSketch);
+ aCenterPnt->setValue(aCenterInSketch);
+ aFocusPnt->setValue(aFocusInSketch);
+ aProjection->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(isInversed);
+
+ aProjection->data()->blockSendAttributeUpdated(aWasBlocked);
+ }
+ else {
+ // ELLIPSE is a projection
+ rebuildProjectedFeature(aProjection, CIRCLE_ELLIPSE_PROJECTION(),
+ SketchPlugin_Ellipse::ID());
+
+ // update attributes of projection
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Ellipse::CENTER_ID()));
+ aCenterPnt->setValue(aCenterInSketch);
+ std::shared_ptr<GeomDataAPI_Point2D> aFocusPnt =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aProjection->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()));
+ aFocusPnt->setValue(aFocusInSketch);
+ aProjection->real(SketchPlugin_Ellipse::MINOR_RADIUS_ID())->setValue(
+ anEllipse.minorRadius());
+ }
+ }
+ else
+ return;
} else
return;
}
}
}
+
+bool SketchPlugin_Projection::rebuildProjectedFeature(
+ FeaturePtr& theProjection,
+ const std::set<std::string>& theSupportedTypes,
+ const std::string& theRequestedFeature)
+{
+ bool isRebuild = false;
+ if (theProjection &&
+ (theSupportedTypes.find(theProjection->getKind()) == theSupportedTypes.end() ||
+ (!theRequestedFeature.empty() && theProjection->getKind() != theRequestedFeature))) {
+ DocumentPtr aDoc = sketch()->document();
+
+ AttributeRefAttrPtr aRefAttr = data()->refattr(PROJECTED_FEATURE_ID());
+ aRefAttr->setObject(data()->owner()); // to not remove of this remove reference to aProjection
+ std::set<FeaturePtr> aFeaturesToBeRemoved;
+ aFeaturesToBeRemoved.insert(theProjection);
+ ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
+ theProjection = FeaturePtr();
+ aRefAttr->setObject(theProjection);
+ isRebuild = true;
+ }
+
+ if (!theProjection && !theRequestedFeature.empty())
+ theProjection = sketch()->addFeature(theRequestedFeature);
+ return isRebuild;
+}
/// \brief Find projection of a feature onto sketch plane
void computeProjection(const std::string& theID);
+ /// \brief Delete already calculated projected feature
+ /// if the selection of the projection is changed
+ /// \param[in/out] theProjection projected feature
+ /// \param[in] theSupportedTypes types supported relatively to the base selection
+ /// \param[in] theRequestedFeature type of the new feature to be created
+ /// (remove only if empty string).
+ bool rebuildProjectedFeature(FeaturePtr& theProjection,
+ const std::set<std::string>& theSupportedTypes,
+ const std::string& theRequestedFeature = std::string());
+
bool myIsComputing;
};
theFeature->setResult(aResult, theIndex);
}
+void SketchPlugin_Sketch::createLine2DResult(ModelAPI_Feature* theFeature,
+ SketchPlugin_Sketch* theSketch,
+ const std::string& theStartAttrID,
+ const std::string& theEndAttrID,
+ const int theIndex)
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aStartAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theStartAttrID));
+ std::shared_ptr<GeomDataAPI_Point2D> anEndAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(theEndAttrID));
+
+ if (!aStartAttr || !aStartAttr->isInitialized() ||
+ !anEndAttr || !anEndAttr->isInitialized())
+ return;
+
+ std::shared_ptr<GeomAPI_Pnt> aStart(theSketch->to3D(aStartAttr->x(), aStartAttr->y()));
+ std::shared_ptr<GeomAPI_Pnt> anEnd(theSketch->to3D(anEndAttr->x(), anEndAttr->y()));
+ //std::cout<<"Execute line "<<aStart->x()<<" "<<aStart->y()<<" "<<aStart->z()<<" - "
+ // <<anEnd->x()<<" "<<anEnd->y()<<" "<<anEnd->z()<<std::endl;
+ // make linear edge
+ std::shared_ptr<GeomAPI_Edge> anEdge = GeomAlgoAPI_EdgeBuilder::line(aStart, anEnd);
+ // store the result
+ std::shared_ptr<ModelAPI_ResultConstruction> aResult =
+ theFeature->document()->createConstruction(theFeature->data(), theIndex);
+ aResult->setShape(anEdge);
+ aResult->setIsInHistory(false);
+ theFeature->setResult(aResult, theIndex);
+}
+
FeaturePtr SketchPlugin_Sketch::addUniqueNamedCopiedFeature(FeaturePtr theFeature,
SketchPlugin_Sketch* theSketch,
const bool theIsCopy)
SketchPlugin_Sketch* theSketch,
const std::string& theAttributeID, const int theIndex);
+ /// \brief Create a result for the segment given by a pair of attributes
+ /// \param theFeature a source feature
+ /// \param theSketch a sketch intance
+ /// \param theStartAttrID an attribute string
+ /// \param theEndAttrID an attribute string
+ /// \param theIndex an index of the result
+ static void createLine2DResult(ModelAPI_Feature* theFeature,
+ SketchPlugin_Sketch* theSketch,
+ const std::string& theStartAttrID,
+ const std::string& theEndAttrID,
+ const int theIndex = 0);
+
/// Add new feature and fill the data of the feature by the data of the parameter feature.
/// The name of the created feature stays unique.
/// \param theFeature a source feature
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 perasentation object
+ // 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]);
}
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomAlgoAPI_ShapeTools.h>
-#include <GeomAlgoAPI_CompoundBuilder.h>
#include <ModelAPI_AttributeBoolean.h>
#include <ModelAPI_AttributeDouble.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMiddle.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintParallel.h>
#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
#include <SketchPlugin_Point.h>
-#include <SketchPlugin_Tools.h>
#include <ModelGeomAlgo_Point2D.h>
#include <ModelAPI_EventReentrantMessage.h>
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_POINT());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), PREVIEW_OBJECT());
-
- // TODO: remove
- //data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeReference::typeId());
- //data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
- //data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
}
void SketchPlugin_Split::execute()
// Check the base objects are initialized.
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
data()->attribute(SELECTED_OBJECT()));
- //ObjectPtr aBaseObject = anObjectAttr->value();
- //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- // aData->attribute(SketchPlugin_Constraint::VALUE()));
if(!aBaseObjectAttr->isInitialized()) {
setError("Error: Base object is not initialized.");
return;
}
ObjectPtr aBaseObject = aBaseObjectAttr->value();
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
- // getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
- // getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
if (!aFirstPointAttrOfSplit.get() || !aFirstPointAttrOfSplit->isInitialized() ||
!aSecondPointAttrOfSplit.get() || !aSecondPointAttrOfSplit->isInitialized()) {
setError("Error: Sub-shape is not initialized.");
return;
}
- /// Remove reference of this feature to feature used in preview, it is not necessary anymore
- /// as trim will be removed after execute
+ // Remove reference of this feature to feature used in preview, it is not necessary anymore
+ // as trim will be removed after execute
AttributeReferencePtr aPreviewObjectAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
data()->attribute(PREVIEW_OBJECT()));
// Find feature constraints
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
- ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
+ ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
std::set<FeaturePtr> aFeaturesToDelete, aFeaturesToUpdate;
//std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
- getConstraints(aFeaturesToDelete, aFeaturesToUpdate, /*aTangentFeatures, */
- aCoincidenceToFeature);
+ getConstraints(aFeaturesToDelete, aFeaturesToUpdate, aCoincidenceToFeature);
std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
std::list<AttributePtr> aRefsToFeature;
- getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
+ SketchPlugin_SegmentationTools::getRefAttributes(
+ aBaseFeature, aBaseRefAttributes, aRefsToFeature);
std::map<AttributePtr, AttributePtr> aBasePointModifiedAttributes;
else if (aFeatureKind == SketchPlugin_Arc::ID())
aNewFeature = splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences,
aCreatedFeatures, aModifiedAttributes);
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+ aNewFeature = splitEllipticArc(aSplitFeature, aBaseFeature, anAfterFeature,
+ aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
restoreCurrentFeature();
- if (aFeatureKind == SketchPlugin_Circle::ID()) {
- FeaturePtr aCircleFeature = aBaseFeature;
- aReplacingFeature = splitCircle(aSplitFeature, aBaseFeature, anAfterFeature,
+ if (aFeatureKind == SketchPlugin_Circle::ID() || aFeatureKind == SketchPlugin_Ellipse::ID()) {
+ aFeaturesToDelete.insert(aBaseFeature);
+ aReplacingFeature = splitClosed(aSplitFeature, aBaseFeature, anAfterFeature,
aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
- updateRefFeatureConstraints(getFeatureResult(aBaseFeature), aRefsToFeature);
+ updateRefFeatureConstraints(aBaseFeature->lastResult(), aRefsToFeature);
- AttributePtr aCenterAttr = aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID());
- aFeaturesToDelete.insert(aCircleFeature);
// as circle is removed, temporary fill this attribute*/
aBaseObjectAttr->setObject(ResultPtr());
}
#endif
std::set<ResultPtr> aFeatureResults;
- aFeatureResults.insert(getFeatureResult(aBaseFeature));
+ aFeatureResults.insert(aBaseFeature->lastResult());
if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
- aFeatureResults.insert(getFeatureResult(anAfterFeature));
+ aFeatureResults.insert(anAfterFeature->lastResult());
// coincidence to feature
updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
aFeatureResults, aSplitFeature, aFeaturesToDelete);
- updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
+ SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
// delete constraints
#ifdef DEBUG_SPLIT
std::cout << std::endl;
}
#endif
- updateFeaturesAfterSplit(aFeaturesToUpdate);
+ SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(aFeaturesToUpdate);
// Send events to update the sub-features by the solver.
if(isUpdateFlushed) {
ResultPtr aReplacingResult;
if (aReplacingFeature.get()) {
aReplacingFeature->execute(); // need it to obtain result
- aReplacingResult = getFeatureResult(aReplacingFeature);
+ aReplacingResult = aReplacingFeature->lastResult();
}
if (aReplacingResult.get()) { // base object was removed
aPreviewObject = aReplacingResult;
aPreviewObject = ObjectPtr();
aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
- aBaseObject = getFeatureResult(aBaseFeature);
+ aBaseObject = aBaseFeature->lastResult();
std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
aPreviewPnt2d->y());
ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
aPreviewObject = aBaseResult;
}
if (!aPreviewObject.get() && aNewFeature.get()) {
- ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
+ ResultPtr aNewFeatureResult = aNewFeature->lastResult();
if (aNewFeatureResult.get()) {
GeomShapePtr aShape = aNewFeatureResult->shape();
std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
if (anObject.get() && aPoint.get()) {
- //if (myCashedShapes.find(anObject) == myCashedShapes.end())
- // fillObjectShapes(anObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
- if (myCashedShapes.find(anObject) == myCashedShapes.end())
- fillObjectShapes(anObject, sketch()->data()->owner());
+ if (myCashedShapes.find(anObject) == myCashedShapes.end()) {
+ SketchPlugin_SegmentationTools::fillObjectShapes(
+ this, anObject, myCashedShapes, myCashedReferences);
+ }
const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
if (aShapes.size() > 1) {
std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
- GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
+ GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
+ SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myCashedReferences);
if (aSelectedShape.get()) {
aFilledAttributeName = SELECTED_OBJECT();
}
AISObjectPtr SketchPlugin_Split::getAISObject(AISObjectPtr thePrevious)
{
- /*AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SketchPlugin_Constraint::VALUE()));
- FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
-
- AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(
- data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
- AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(
- data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
-
- if (aBaseObjectAttr->isInitialized() && aBaseFeature.get() &&
- aFirstPointAttrOfSplit->isInitialized() &&
- aSecondPointAttrOfSplit->isInitialized()) {
-
- ResultPtr aResult = getFeatureResult(aBaseFeature);
- GeomShapePtr aBaseShape = aResult->shape();
- std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
-
- std::shared_ptr<GeomAPI_Pnt2d> aStartPnt2d = aFirstPointAttrOfSplit->pnt();
- std::shared_ptr<GeomAPI_Pnt> aStartPoint = sketch()->to3D(aStartPnt2d->x(), aStartPnt2d->y());
- aPoints.push_back(aStartPoint);
-
- std::shared_ptr<GeomAPI_Pnt2d> aSecondPnt2d = aSecondPointAttrOfSplit->pnt();
- std::shared_ptr<GeomAPI_Pnt> aSecondPoint =
- sketch()->to3D(aSecondPnt2d->x(), aSecondPnt2d->y());
- aPoints.push_back(aSecondPoint);
-
- std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
-
- GeomAlgoAPI_ShapeTools::splitShape_p(aBaseShape, aPoints, aSplitShapes);
- std::shared_ptr<GeomAPI_Shape> aShape =
- GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
-
- AISObjectPtr anAIS = thePrevious;
- if (aShape) {
- if (!anAIS)
- anAIS = AISObjectPtr(new GeomAPI_AISObject);
- anAIS->createShape(aShape);
- std::shared_ptr<ModelAPI_AttributeBoolean> anAuxiliaryAttr =
- aBaseFeature->data()->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID());
-
- bool isConstruction = anAuxiliaryAttr.get() != NULL && anAuxiliaryAttr->value();
-
- std::vector<int> aColor;
- double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
- int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
- if (isConstruction) {
- aColor = Config_PropManager::color("Visualization", "sketch_auxiliary_color");
- aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH_AUXILIARY();
- aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE_AUXILIARY();
- }
- else {
- aColor = Config_PropManager::color("Visualization", "sketch_entity_color");
- }
- anAIS->setColor(aColor[0], aColor[1], aColor[2]);
- anAIS->setWidth(aWidth + 1);
- anAIS->setLineStyle(aLineStyle);
- }
- return anAIS;
- }
- return AISObjectPtr();*/
-#ifdef DEBUG_SPLIT
- std::cout << "SketchPlugin_Split::getAISObject: " << data()->name() << std::endl;
-#endif
-
- AISObjectPtr anAIS = thePrevious;
-
- std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
- GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT());
- if (aPreviewShape.get())
- aShapes.push_back(aPreviewShape);
- GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
- if (aSelectedShape.get())
- aShapes.push_back(aSelectedShape);
-
- if (aShapes.empty())
- return AISObjectPtr();
-
- GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
- if (!aBaseShape.get())
- return AISObjectPtr();
-
- if (aBaseShape.get()) {
- if (!anAIS)
- anAIS = AISObjectPtr(new GeomAPI_AISObject);
- anAIS->createShape(aBaseShape);
-
- std::vector<int> aColor;
- aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
- double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
- int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
- anAIS->setColor(aColor[0], aColor[1], aColor[2]);
- // width when there is not base object should be extened in several points
- // in order to see this preview over highlight
- anAIS->setWidth(aWidth+4);
- anAIS->setLineStyle(aLineStyle);
- }
- else
- anAIS = AISObjectPtr();
- return anAIS;
+ return SketchPlugin_SegmentationTools::getAISObject(thePrevious,
+ this, PREVIEW_OBJECT(), PREVIEW_POINT(), SELECTED_OBJECT(), SELECTED_POINT());
}
//********************************************************************
-void SketchPlugin_Split::fillObjectShapes(const ObjectPtr& theObject,
- const ObjectPtr& theSketch)
-{
- std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
- std::map<std::shared_ptr<GeomDataAPI_Point2D>, std::shared_ptr<GeomAPI_Pnt> > aPointToAttributes;
- std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
- // current feature
- FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- // edges on feature
- std::set<ResultPtr> anEdgeResults;
- ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeResults);
- if (!anEdgeResults.empty()) {
- GeomShapePtr aFeatureShape = (*anEdgeResults.begin())->shape();
-
- // coincidences to the feature
- ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
- aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
- // layed on feature coincidences to divide it on several shapes
- std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
- std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
- aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aData->attribute(SketchPlugin_Sketch::NORM_ID()));
- std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
- std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
- ModelGeomAlgo_Point2D::getPointsInsideShape_p(aFeatureShape, aRefAttributes, aC->pnt(),
- aX->dir(), aY, aPoints, aPointToAttributes);
-
- if (!aPoints.empty())
- GeomAlgoAPI_ShapeTools::splitShape_p(aFeatureShape, aPoints, aShapes);
- }
- myCashedShapes[theObject] = aShapes;
- myCashedReferences[theObject] = aPointToAttributes;
-}
-
-GeomShapePtr SketchPlugin_Split::getSubShape(const std::string& theObjectAttributeId,
- const std::string& thePointAttributeId)
-{
- GeomShapePtr aBaseShape;
-
- AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(theObjectAttributeId));
- ObjectPtr aBaseObject = anObjectAttr->value();
- if (!aBaseObject.get())
- return aBaseShape;
-
- // point on feature
- AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- data()->attribute(thePointAttributeId));
- std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
- std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
- anAttributePnt2d->y());
-
-#ifdef TRIM_SHAPE
- if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
- fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
-
- const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
- if (!aShapes.empty()) {
- std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
- for (; anIt != aLast; anIt++) {
- GeomShapePtr aShape = *anIt;
- std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
- if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint))
- aBaseShape = aShape;
- }
- }
-#else
- if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
- fillObjectShapes(aBaseObject, sketch()->data()->owner());
-
- std::shared_ptr<GeomAPI_Pnt> aStartPoint;
- std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
- const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
- std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
- for (; anIt != aLast; anIt++) {
- GeomShapePtr aCurrentShape = *anIt;
- std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
- if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
- if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
- std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
- aStartPoint = anEdge->firstPoint();
- aSecondPoint = anEdge->lastPoint();
- }
- break;
- }
- }
-
- if (!aStartPoint.get() || !aSecondPoint.get())
- return aBaseShape;
-
- //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- // data()->attribute(SketchPlugin_Constraint::VALUE()));
- FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject/*aBaseObjectAttr->value()*/);
-
- //AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(
- // data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
- //AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(
- // data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
- if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
- //aFirstPointAttrOfSplit->isInitialized() &&
- //aSecondPointAttrOfSplit->isInitialized()) {
- ResultPtr aResult = getFeatureResult(aBaseFeature);
- GeomShapePtr aResultShape = aResult->shape();
- std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
-
- //std::shared_ptr<GeomAPI_Pnt2d> aStartPnt2d = aFirstPointAttrOfSplit->pnt();
- //std::shared_ptr<GeomAPI_Pnt> aStartPoint = sketch()->to3D(aStartPnt2d->x(), aStartPnt2d->y());
- aPoints.push_back(aStartPoint);
-
- //std::shared_ptr<GeomAPI_Pnt2d> aSecondPnt2d = aSecondPointAttrOfSplit->pnt();
- //std::shared_ptr<GeomAPI_Pnt> aSecondPoint =
- // sketch()->to3D(aSecondPnt2d->x(), aSecondPnt2d->y());
- aPoints.push_back(aSecondPoint);
-
- std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
- GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
- aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
-#endif
- }
- return aBaseShape;
-}
-
-void SketchPlugin_Split::getFeaturePoints(const FeaturePtr& theFeature,
- AttributePoint2DPtr& theStartPointAttr,
- AttributePoint2DPtr& theEndPointAttr)
-{
- std::string aFeatureKind = theFeature->getKind();
- std::string aStartAttributeName, anEndAttributeName;
- if (aFeatureKind == SketchPlugin_Line::ID()) {
- aStartAttributeName = SketchPlugin_Line::START_ID();
- anEndAttributeName = SketchPlugin_Line::END_ID();
- }
- else if (aFeatureKind == SketchPlugin_Arc::ID()) {
- aStartAttributeName = SketchPlugin_Arc::START_ID();
- anEndAttributeName = SketchPlugin_Arc::END_ID();
- }
- if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
- theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theFeature->attribute(aStartAttributeName));
- theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theFeature->attribute(anEndAttributeName));
- }
-}
-
void SketchPlugin_Split::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
std::set<FeaturePtr>& theFeaturesToUpdate,
std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature)
// Check the base objects are initialized.
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
data()->attribute(SELECTED_OBJECT()));
- //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- // aData->attribute(SketchPlugin_Constraint::VALUE()));
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
+ ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
theFeaturesToDelete.insert(aRefFeature);
else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID())
theFeaturesToUpdate.insert(aRefFeature);
- else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) {
+ else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID() ||
+ aRefFeatureKind == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
std::string anAttributeToBeModified;
AttributePoint2DPtr aCoincidentPoint;
AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
bool isToFeature = false;
- if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature
+ if (anAttrA->isObject() || anAttrB->isObject()) { // coincidence to base feature
FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
: FeaturePtr();
isToFeature = aFeature.get() && aFeature == aBaseFeature;
if (isToFeature)
aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
}
- if (!isToFeature) { /// coincidence to point on base feature
+ if (!isToFeature) { // coincidence to point on base feature
AttributePtr anAttribute;
if (!anAttrA->isObject()) {
}
}
-void SketchPlugin_Split::getRefAttributes(const FeaturePtr& theFeature,
- std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
- std::list<AttributePtr>& theRefsToFeature)
-{
- theRefs.clear();
-
- std::list<AttributePtr> aPointAttributes =
- theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::set<AttributePtr> aPointAttributesSet;
-
- std::list<AttributePtr>::const_iterator aPIt =
- aPointAttributes.begin(), aPLast = aPointAttributes.end();
- for (; aPIt != aPLast; aPIt++)
- aPointAttributesSet.insert(*aPIt);
-
- std::set<AttributePtr> aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe();
- std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
- aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
-
- std::set<AttributePtr>::const_iterator aIt;
- for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
- AttributePtr anAttr = (*aIt);
- FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
- if (anAttrFeature.get() != this &&
- anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
- if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes
- AttributePtr anAttrInRef = aRefAttr->attr();
- if (anAttrInRef.get() &&
- aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
- if (theRefs.find(anAttrInRef) != theRefs.end())
- theRefs[anAttrInRef].push_back(aRefAttr);
- else {
- std::list<AttributePtr> anAttrList;
- anAttrList.push_back(aRefAttr);
- theRefs[anAttrInRef] = anAttrList;
- }
- }
- }
- else { /// find attributes referenced to feature itself
- theRefsToFeature.push_back(anAttr);
- }
- }
- }
-}
-
void SketchPlugin_Split::updateCoincidenceConstraintsToFeature(
const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
// we should build coincidence constraints to end of the split feature
std::set<std::shared_ptr<GeomDataAPI_Point2D> > aNewCoincidencesToSplitFeature;
AttributePoint2DPtr aStartPointAttr, anEndPointAttr;
- getFeaturePoints(theSplitFeature, aStartPointAttr, anEndPointAttr);
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ theSplitFeature, aStartPointAttr, anEndPointAttr);
if (theFurtherCoincidences.find(aStartPointAttr) == theFurtherCoincidences.end())
aNewCoincidencesToSplitFeature.insert(aStartPointAttr);
if (theFurtherCoincidences.find(anEndPointAttr) == theFurtherCoincidences.end())
aNewCoincidencesToSplitFeature.insert(anEndPointAttr);
std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
- aCLast = theCoincidenceToFeature.end();
+ aCLast = theCoincidenceToFeature.end();
#ifdef DEBUG_SPLIT
std::cout << std::endl;
std::cout << "Coincidences to feature(modified):"<< std::endl;
}
}
else {
- /// find feature by shape intersected the point
+ // find feature by shape intersected the point
ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
if (theFeatureResults.size() > 1) { // try to find point on additional feature
}
}
-void SketchPlugin_Split::updateRefAttConstraints(
- const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
- const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
-{
-#ifdef DEBUG_SPLIT
- std::cout << "SketchPlugin_Split::updateRefAttConstraints" << std::endl;
-#endif
-
- std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
- anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
- for (; anIt != aLast; anIt++) {
- AttributePtr anAttribute = anIt->first;
-
- /// not found in references
- if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
- continue;
- std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
- std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
- aRLast = aRefAttributes.end();
-
- AttributePtr aNewAttribute = anIt->second;
- for (; aRefIt != aRLast; aRefIt++) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
- if (aRefAttr.get()) {
- aRefAttr->setAttr(aNewAttribute);
-#ifdef DEBUG_SPLIT
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
- std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
-#endif
- }
- }
- }
-}
-
FeaturePtr SketchPlugin_Split::splitLine(FeaturePtr& theSplitFeature,
- FeaturePtr& theBaseFeatureModified,
- FeaturePtr& theAfterFeature,
- std::set<AttributePoint2DPtr>& thePoints,
- std::set<FeaturePtr>& theCreatedFeatures,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
{
FeaturePtr anNewFeature;
FeaturePtr aConstraintFeature;
theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch)
- return anNewFeature;
-
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
data()->attribute(SELECTED_OBJECT()));
- //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- // data()->attribute(SketchPlugin_Constraint::VALUE()));
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- std::string aFeatureKind = aBaseFeature->getKind();
- if (aFeatureKind != SketchPlugin_Line::ID())
- return anNewFeature;
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
- //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
- //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
- getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
setError("Error: Feature has no start and end points.");
return anNewFeature;
ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
#endif
- /// create a split feature
- theSplitFeature =
- createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ // create a split feature
+ theSplitFeature = SketchPlugin_SegmentationTools::createLineFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
theCreatedFeatures.insert(theSplitFeature);
// before split feature
theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
}
else {
- theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
- /// move end arc point to start of split
+ theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
+ // move end arc point to start of split
}
// after split feature
if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
FeaturePtr aFeature;
if (!theBaseFeatureModified.get()) {
- aFeature = aBaseFeature; ///< use base feature to store all constraints here
+ aFeature = aBaseFeature; // use base feature to store all constraints here
fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
aFeature->execute(); // to update result
}
else {
- aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
+ aFeature = SketchPlugin_SegmentationTools::createLineFeature(
+ aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
theCreatedFeatures.insert(aFeature);
theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
aFeature->attribute(SketchPlugin_Line::END_ID())));
// (after the after feature creation). Otherwise modified value will be used in after feature
// before split feature
if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
- /// move end arc point to start of split
+ // move end arc point to start of split
fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
aFirstPointAttrOfSplit);
theBaseFeatureModified->execute(); // to update result
// additional constraints between split and base features
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintParallel::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(theSplitFeature));
+ aBaseFeature->lastResult(),
+ theSplitFeature->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
if (theAfterFeature.get()) {
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintParallel::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(theAfterFeature));
+ aBaseFeature->lastResult(),
+ theAfterFeature->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
}
#endif
}
FeaturePtr SketchPlugin_Split::splitArc(FeaturePtr& theSplitFeature,
- FeaturePtr& theBaseFeatureModified,
- FeaturePtr& theAfterFeature,
- std::set<AttributePoint2DPtr>& thePoints,
- std::set<FeaturePtr>& theCreatedFeatures,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
{
FeaturePtr anNewFeature;
FeaturePtr aConstraintFeature;
theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch)
- return anNewFeature;
-
- AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SELECTED_OBJECT()));
- //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- // data()->attribute(SketchPlugin_Constraint::VALUE()));
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- std::string aFeatureKind = aBaseFeature->getKind();
- if (aFeatureKind != SketchPlugin_Arc::ID())
- return anNewFeature;
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
- //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
- //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
- getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
setError("Error: Feature has no start and end points.");
return anNewFeature;
ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
#endif
- /// split feature
- theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ // split feature
+ theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
theCreatedFeatures.insert(theSplitFeature);
// before split feature
theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
}
else {
- theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
- /// move end arc point to start of split
+ theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
+ // move end arc point to start of split
}
// after split feature
if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
FeaturePtr aFeature;
if (!theBaseFeatureModified.get()) {
- aFeature = aBaseFeature; ///< use base feature to store all constraints here
+ aFeature = aBaseFeature; // use base feature to store all constraints here
fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
aFeature->execute(); // to update result
}
else {
- aFeature = createArcFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
+ aFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
theCreatedFeatures.insert(aFeature);
theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
aFeature->attribute(SketchPlugin_Arc::END_ID())));
// (after the after feature creation). Otherwise modified value will be used in after feature
// before split feature
if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
- /// move end arc point to start of split
+ // move end arc point to start of split
fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
aFirstPointAttrOfSplit);
theBaseFeatureModified->execute(); // to update result
#ifdef CREATE_CONSTRAINTS
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintEqual::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(theSplitFeature));
+ aBaseFeature->lastResult(),
+ theSplitFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintTangent::ID(),
+ theSplitFeature->lastResult(),
+ aBaseFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ if (theAfterFeature.get()) {
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintEqual::ID(),
+ aBaseFeature->lastResult(),
+ theAfterFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintTangent::ID(),
+ theSplitFeature->lastResult(),
+ theAfterFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ }
+#endif
+ return anNewFeature;
+}
+
+FeaturePtr SketchPlugin_Split::splitEllipticArc(FeaturePtr& theSplitFeature,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
+{
+ FeaturePtr anNewFeature;
+
+ std::set<FeaturePtr> aCreatedFeatures;
+ FeaturePtr aConstraintFeature;
+ theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
+
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
+ FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
+
+ AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
+ AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
+ AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
+ setError("Error: Feature has no start and end points.");
+ return anNewFeature;
+ }
+
+ arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
+ aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+#ifdef DEBUG_SPLIT
+ std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
+ std::cout << "Start point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
+ std::cout << "1st point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
+ std::cout << "2nd point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
+ std::cout << "End point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
+#endif
+
+ // split feature
+ theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
+ theCreatedFeatures.insert(theSplitFeature);
+
+ // before split feature
+ if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
+ theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+ }
+ else {
+ theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
+ // move end arc point to start of split
+ }
+
+ // after split feature
+ if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
+ FeaturePtr aFeature;
+ if (!theBaseFeatureModified.get()) {
+ aFeature = aBaseFeature; // use base feature to store all constraints here
+ fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
+ aFeature->execute(); // to update result
+ }
+ else {
+ aFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
+ theCreatedFeatures.insert(aFeature);
+ theModifiedAttributes.insert(std::make_pair(
+ anEndPointAttrOfBase, aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ anNewFeature = aFeature;
+ }
+ aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
+ SketchPlugin_ConstraintCoincidence::ID(),
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ theCreatedFeatures.insert(aConstraintFeature);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+
+ if (!theBaseFeatureModified.get())
+ theBaseFeatureModified = aFeature;
+ else
+ theAfterFeature = aFeature;
+ }
+ else {
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ }
+ // base split, that is defined before split feature should be changed at end
+ // (after the after feature creation). Otherwise modified value will be used in after feature
+ // before split feature
+ if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
+ // move end arc point to start of split
+ fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ aFirstPointAttrOfSplit);
+ theBaseFeatureModified->execute(); // to update result
+ aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
+ SketchPlugin_ConstraintCoincidence::ID(),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ theCreatedFeatures.insert(aConstraintFeature);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ }
+ else
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+
+ // additional constraints between split and base features
+#ifdef CREATE_CONSTRAINTS
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintEqual::ID(),
+ aBaseFeature->lastResult(),
+ theSplitFeature->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintTangent::ID(),
- getFeatureResult(theSplitFeature),
- getFeatureResult(aBaseFeature));
+ theSplitFeature->lastResult(),
+ aBaseFeature->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
if (theAfterFeature.get()) {
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintEqual::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(theAfterFeature));
+ aBaseFeature->lastResult(),
+ theAfterFeature->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintTangent::ID(),
- getFeatureResult(theSplitFeature),
- getFeatureResult(theAfterFeature));
+ theSplitFeature->lastResult(),
+ theAfterFeature->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
}
#endif
return anNewFeature;
}
-FeaturePtr SketchPlugin_Split::splitCircle(FeaturePtr& theSplitFeature,
+FeaturePtr SketchPlugin_Split::splitClosed(FeaturePtr& theSplitFeature,
FeaturePtr& theBaseFeatureModified,
FeaturePtr& theAfterFeature,
std::set<AttributePoint2DPtr>& thePoints,
FeaturePtr aConstraintFeature;
theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch)
- return anNewFeature;
-
- AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SELECTED_OBJECT()));
- //AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- // data()->attribute(SketchPlugin_Constraint::VALUE()));
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- std::string aFeatureKind = aBaseFeature->getKind();
- if (aFeatureKind != SketchPlugin_Circle::ID())
- return anNewFeature;
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
- //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
- //getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
- /// split feature
- theSplitFeature =
- createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
- bool aSplitReversed = std::dynamic_pointer_cast<SketchPlugin_Arc>(theSplitFeature)->isReversed();
+ // split feature
+ theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
+ const std::string& aReversedAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+ bool aSplitReversed = theSplitFeature->boolean(aReversedAttrName)->value();
theCreatedFeatures.insert(theSplitFeature);
- /// base feature is a left part of the circle
- theBaseFeatureModified = createArcFeature(aBaseFeature,
- aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ // base feature is a left part of the circle
+ theBaseFeatureModified = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
anNewFeature = theBaseFeatureModified;
- std::dynamic_pointer_cast<SketchPlugin_Arc>(
- theBaseFeatureModified)->setReversed(!aSplitReversed);
+ theBaseFeatureModified->boolean(aReversedAttrName)->setValue(!aSplitReversed);
theBaseFeatureModified->execute();
- theModifiedAttributes.insert(
- std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
- theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
+ if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
+ }
+ else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
+
+ // update the PARENT_ID reference for all the features created by the ellipse
+ const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
+ std::list<AttributePtr> aRefsToParent;
+ for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
+ if ((*aRef)->id() == SketchPlugin_Line::PARENT_ID() ||
+ (*aRef)->id() == SketchPlugin_Point::PARENT_ID())
+ aRefsToParent.push_back(*aRef);
+ }
+ for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
+ aRef != aRefsToParent.end(); ++aRef)
+ std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(theSplitFeature);
+ }
theCreatedFeatures.insert(theBaseFeatureModified);
+ const std::string& aStartAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
+ const std::string& aEndAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
+
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
+ (theBaseFeatureModified->attribute(aStartAttrName)));
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
+ (theBaseFeatureModified->attribute(aEndAttrName)));
// additional constraints between split and base features
aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
SketchPlugin_ConstraintCoincidence::ID(),
- theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
- theSplitFeature->attribute(SketchPlugin_Arc::END_ID()));
+ theBaseFeatureModified->attribute(aEndAttrName),
+ theSplitFeature->attribute(aEndAttrName));
theCreatedFeatures.insert(aConstraintFeature);
aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
SketchPlugin_ConstraintCoincidence::ID(),
- theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()),
- theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
+ theBaseFeatureModified->attribute(aStartAttrName),
+ theSplitFeature->attribute(aStartAttrName));
theCreatedFeatures.insert(aConstraintFeature);
#ifdef CREATE_CONSTRAINTS
aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
SketchPlugin_ConstraintTangent::ID(),
- getFeatureResult(theSplitFeature),
- getFeatureResult(theBaseFeatureModified));
+ theSplitFeature->lastResult(),
+ theBaseFeatureModified->lastResult());
theCreatedFeatures.insert(aConstraintFeature);
#endif
return anNewFeature;
{
static const double anAngleTol = 1.e-12;
+ const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
+ const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+
std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
- bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+ theArc->attribute(aCenterAttrName))->pnt();
+ bool isReversed = theArc->boolean(aReversedAttrName)->value();
// collect directions to each point
std::shared_ptr<GeomAPI_Dir2d> aStartDir(
}
}
-FeaturePtr SketchPlugin_Split::createLineFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr)
-{
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
-
- fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPointAttr);
- fillAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPointAttr);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- aFeature->execute(); // to obtain result
-
- return aFeature;
-}
-
-FeaturePtr SketchPlugin_Split::createArcFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr)
-{
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- std::string aCenterAttributeId;
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
- aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
- else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
- aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
-
- if (aCenterAttributeId.empty())
- return aFeature;
-
- aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
- // update fillet arc: make the arc correct for sure, so, it is not needed to process
- // the "attribute updated"
- // by arc; moreover, it may cause cyclicity in hte mechanism of updater
- bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
-
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
- theBaseFeature->attribute(aCenterAttributeId));
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- /// fill referersed state of created arc as it is on the base arc
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
- bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
- aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
- }
- aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
- aFeature->execute(); // to obtain result
-
- return aFeature;
-}
-
-void SketchPlugin_Split::updateFeaturesAfterSplit(
- const std::set<FeaturePtr>& theFeaturesToUpdate)
-{
- std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
- aLast = theFeaturesToUpdate.end();
- for (; anIt != aLast; anIt++) {
- FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
- std::string aRefFeatureKind = aRefFeature->getKind();
- if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
- std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
- std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
- if (aLenghtFeature.get()) {
- std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
- double aValue;
- if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
- aValueAttr->setValue(aValue);
- }
- }
- }
-}
-
-std::shared_ptr<ModelAPI_Result> SketchPlugin_Split::getFeatureResult(
- const std::shared_ptr<ModelAPI_Feature>& theFeature)
-{
- std::shared_ptr<ModelAPI_Result> aResult;
-
- std::string aFeatureKind = theFeature->getKind();
- if (aFeatureKind == SketchPlugin_Line::ID())
- aResult = theFeature->firstResult();
- else if (aFeatureKind == SketchPlugin_Arc::ID())
- aResult = theFeature->lastResult();
- else if (aFeatureKind == SketchPlugin_Circle::ID())
- aResult = theFeature->lastResult();
-
- return aResult;
-}
-
#ifdef _DEBUG
std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_Split::getEdgeAttributes(
const std::shared_ptr<ModelAPI_Feature>& theFeature)
anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
}
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
+ anAttributes.insert(theFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ anAttributes.insert(theFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ }
else if (aFeatureKind == SketchPlugin_Circle::ID()) {
}
{
std::shared_ptr<GeomDataAPI_Point2D> anAttribute;
- GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
+ GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
+ SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myCashedReferences);
if (!aSelectedShape.get())
return anAttribute;
std::shared_ptr<GeomAPI_Pnt> aLastPnt = anEdge->lastPoint();
std::shared_ptr<GeomDataAPI_Point2D> aFirstPointAttr, aLastPointAttr;
- /// find the points in feature attributes
+ // find the points in feature attributes
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
std::list<AttributePtr> a2DPointAttributes = aBaseFeature->data()->attributes(
GeomDataAPI_Point2D::typeId());
aLastPointAttr = anAttributePoint;
}
- /// find the points in coincident features
- PntToAttributesMap aRefAttributes = myCashedReferences[aBaseObject];
- PntToAttributesMap::const_iterator
+ // find the points in coincident features
+ const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefAttributes = myCashedReferences.at(aBaseObject);
+ GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator
aRIt = aRefAttributes.begin(), aRLast = aRefAttributes.end();
for (; aRIt != aRLast; aRIt++) {
- std::shared_ptr<GeomDataAPI_Point2D> anAttribute = aRIt->first;
- std::shared_ptr<GeomAPI_Pnt> aPoint = aRIt->second;
+ const std::list<AttributePoint2DPtr>& anAttributes = aRIt->second.first;
+ GeomPointPtr aPoint = aRIt->first;
if (!aFirstPointAttr.get() && aFirstPnt->isEqual(aPoint))
- aFirstPointAttr = anAttribute;
+ aFirstPointAttr = anAttributes.front();
if (!aLastPointAttr.get() && aLastPnt->isEqual(aPoint))
- aLastPointAttr = anAttribute;
+ aLastPointAttr = anAttributes.front();
if (aFirstPointAttr.get() && aLastPointAttr.get())
break;
}
if (isUseAttributesInfo) {
std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
getEdgeAttributes(theFeature));
- /// processing of feature with point 2d attributes, like line, arc, circle
+ // processing of feature with point 2d attributes, like line, arc, circle
if (!aPointsInfo.empty()) {
anInfo += ": ";
anInfo += "\n";
anInfo += aPointsInfo;
}
- else { /// process constraint coincidence, find points in ref attr attributes
+ else { // process constraint coincidence, find points in ref attr attributes
std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
ModelAPI_AttributeRefAttr::typeId());
std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
#define SketchPlugin_Split_H_
#include "SketchPlugin.h"
+#include "SketchPlugin_Tools.h"
-#include "GeomAPI_IPresentable.h"
+#include <GeomAPI_IPresentable.h>
#include <ModelAPI_IReentrant.h>
#include <SketchPlugin_Sketch.h>
* \ingroup Plugins
* \brief Feature for creation of a new constraint splitting object. Entities for split:
* - Linear segment by point(s) on this line
- * - Arc by point(s) on this arc
- * - Circle by at least 2 split-points on this circle
+ * - Circular/elliptic arc by point(s) on this arc
+ * - Circle/ellipse by at least 2 split-points on it
*
* The following constraints will be applied after split to keep the divided segments geometry:
* - Coincident constraints for both parts of created segments in the point of splitting
- * - For linear segments parallel, for circles - tangent constraint, for arc - tangent and equal
- * constraints. In case of three segments in result two couple of constraints are created
+ * - For linear segments parallel, for circles/ellipses - tangent constraint,
+ * for arc - tangent and equal constraints. In case of three segments in result
+ * two couple of constraints are created
* - parallel and equal constraints: the first is between 1st and middle entity, the second is
* between 1st and 3rd.
* - tangency constraints: the first between 1st and 2nd, the second between 2nd and 3rd.
* start point of arc/line.
* - Replication constraint used split feature will be deleted in the same way as it is deleted
* by any of entity delete in sketch which is used in this constraint.
- *
- * This constraint has three attributes:
- * SketchPlugin_Constraint::VALUE() contains reference object to be splitted
- * SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B() for the points of split;
- *
*/
class SketchPlugin_Split : public SketchPlugin_Feature, public GeomAPI_IPresentable,
public ModelAPI_IReentrant
virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
private:
- /// Fulfill an internal container by shapes obtained from the parameter object
- /// Shapes are result of split operation by points coincident to shape of the object
- /// \param theObject a source object (will be splitted)
- /// \param theSketch a sketch object
- void fillObjectShapes(const ObjectPtr& theObject, const ObjectPtr& theSketch);
-
- GeomShapePtr getSubShape(const std::string& theObjectAttributeId,
- const std::string& thePointAttributeId);
- /// Returns geom point attribute of the feature bounds. It processes line or arc.
- /// For circle feature, the result attributes are null
- /// \param theFeature a source feature
- /// \param theStartPointAttr an out attribute to start point
- /// \param theStartPointAttr an out attribute to end point
- void getFeaturePoints(const FeaturePtr& theFeature,
- std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
- std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr);
-
/// Obtains those constraints of the feature that should be modified. output maps contain
/// point of coincidence and attribute id to be modified after split
/// \param theFeaturesToDelete [out] constrains that will be deleted after split
std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToUpdate,
std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature);
- /// Obtains references to feature point attributes and to feature,
- /// e.g. for feature line: 1st container is
- /// <1st line point, list<entity_a in distance, entity_b in parallel> >
- /// <2nd line point, list<> >
- /// for feature circle 2nd container is <entity_a in Radius, entity_b in equal, ...>
- /// \param theFeature an investigated feature
- /// \param theRefs a container of list of referenced attributes
- void getRefAttributes(const FeaturePtr& theFeature,
- std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
- std::list<AttributePtr>& theRefsToFeature);
-
/// Move coincidence constraint from feature to point if it is found
/// \param theCoincidenceToFeature coincidence to feature to be connected to new feature
/// \param theFurtherCoincidences a list of points where coincidences will be build
void updateRefFeatureConstraints(const std::shared_ptr<ModelAPI_Result>& theFeatureBaseResult,
const std::list<AttributePtr>& theRefsToFeature);
- /// Move constraints from attribute of base feature to attribute after modification
- /// \param theBaseRefAttributes container of references to the attributes of base feature
- /// \param theModifiedAttributes container of attributes placed instead of base attributes
- /// at the same place
- void updateRefAttConstraints(
- const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
- const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes);
-
/// Make the base object is splitted by the point attributes
/// \param theSplitFeature a result split feature
/// \param theBeforeFeature a feature between start point and the 1st point of split feature
std::set<std::shared_ptr<ModelAPI_Feature>>& theCreatedFeatures,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+ /// Make the base object is splitted by the point attributes
+ /// \param theSplitFeature a result split feature
+ /// \param theBeforeFeature a feature between start point and the 1st point of split feature
+ /// \param theAfterFeature a feature between last point of split feature and the end point
+ /// \param thePoints a list of points where coincidences will be build
+ /// \param theCreatedFeatures a container of created features
+ /// \return new elliptic arc if it was created
+ FeaturePtr splitEllipticArc(std::shared_ptr<ModelAPI_Feature>& theSplitFeature,
+ std::shared_ptr<ModelAPI_Feature>& theBeforeFeature,
+ std::shared_ptr<ModelAPI_Feature>& theAfterFeature,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
+ std::set<std::shared_ptr<ModelAPI_Feature>>& theCreatedFeatures,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+
/// Make the base object is splitted by the point attributes
/// \param theSplitFeature a result split feature
/// \param theBeforeFeature a feature between start point and the 1st point of split feature
/// \param thePoints a list of points where coincidences will be build
/// \param theCreatedFeatures a container of created features
/// \return new arc if it was created
- FeaturePtr splitCircle(std::shared_ptr<ModelAPI_Feature>& theSplitFeature,
+ FeaturePtr splitClosed(std::shared_ptr<ModelAPI_Feature>& theSplitFeature,
std::shared_ptr<ModelAPI_Feature>& theBeforeFeature,
std::shared_ptr<ModelAPI_Feature>& theAfterFeature,
std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
void fillAttribute(const AttributePtr& theModifiedAttribute,
const AttributePtr& theSourceAttribute);
- /// Creates a line feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createLineFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr);
-
- /// Creates an arc feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr);
-
- /// Add feature coincidence constraint between given attributes
- /// \param theFeaturesToUpdate a constraint index
- void updateFeaturesAfterSplit(const std::set<FeaturePtr>& theFeaturesToUpdate);
-
- /// Result result of the feature to build constraint with. For arc, circle it is an edge result.
- /// \param theFeature a feature
- /// \return result object
- std::shared_ptr<ModelAPI_Result> getFeatureResult(
- const std::shared_ptr<ModelAPI_Feature>& theFeature);
-
/// Returns attributes of the feature, used in edge build, for arc it is end and start points
/// \param theFeature a feature
/// \return container of attributes
const bool isUseAttributesInfo = true);
#endif
private:
- typedef std::map<std::shared_ptr<GeomDataAPI_Point2D>,
- std::shared_ptr<GeomAPI_Pnt> > PntToAttributesMap;
std::map<std::shared_ptr<ModelAPI_Object>, std::set<GeomShapePtr> > myCashedShapes;
- std::map<std::shared_ptr<ModelAPI_Object>, PntToAttributesMap> myCashedReferences;
+ std::map<std::shared_ptr<ModelAPI_Object>,
+ GeomAlgoAPI_ShapeTools::PointToRefsMap> myCashedReferences;
};
#endif
#include "SketchPlugin_Tools.h"
+#include "SketchPlugin_Arc.h"
+#include "SketchPlugin_Circle.h"
#include "SketchPlugin_ConstraintCoincidence.h"
+#include "SketchPlugin_ConstraintCoincidenceInternal.h"
#include "SketchPlugin_ConstraintLength.h"
#include "SketchPlugin_ConstraintTangent.h"
+#include "SketchPlugin_Ellipse.h"
+#include "SketchPlugin_EllipticArc.h"
#include "SketchPlugin_Line.h"
#include "SketchPlugin_Point.h"
+#include "SketchPlugin_Projection.h"
#include "SketchPlugin_SketchEntity.h"
+#include "SketchPlugin_Split.h"
+#include "SketchPlugin_Trim.h"
#include <SketcherPrs_Tools.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelGeomAlgo_Point2D.h>
+#include <ModelGeomAlgo_Shape.h>
+
#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Edge.h>
#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_XY.h>
+#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
return aConstraint;
}
+void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theEllipsePoint)
+{
+ SketchPlugin_Sketch* aSketch =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
+
+ FeaturePtr aPointFeature = aSketch->addFeature(SketchPlugin_Point::ID());
+ aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+ aPointFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
+
+ AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipseFeature->attribute(theEllipsePoint));
+
+ AttributePoint2DPtr aCoord = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aPointFeature->attribute(SketchPlugin_Point::COORD_ID()));
+ aCoord->setValue(anElPoint->x(), anElPoint->y());
+
+ aPointFeature->execute();
+ std::string aName = theEllipseFeature->name() + "_" + theEllipsePoint;
+ aPointFeature->data()->setName(aName);
+ aPointFeature->lastResult()->data()->setName(aName);
+
+ createConstraintAttrAttr(aSketch,
+ SketchPlugin_ConstraintCoincidenceInternal::ID(), anElPoint, aCoord);
+}
+
+void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theStartPoint,
+ const std::string& theEndPoint)
+{
+ SketchPlugin_Sketch* aSketch =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theEllipseFeature)->sketch();
+
+ FeaturePtr aLineFeature = aSketch->addFeature(SketchPlugin_Line::ID());
+ aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true);
+ aLineFeature->reference(SketchPlugin_Point::PARENT_ID())->setValue(theEllipseFeature);
+
+ AttributePoint2DPtr aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipseFeature->attribute(theStartPoint));
+ AttributePoint2DPtr aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theEllipseFeature->attribute(theEndPoint));
+
+ AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::START_ID()));
+ aLineStart->setValue(aStartPoint->x(), aStartPoint->y());
+
+ AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aLineFeature->attribute(SketchPlugin_Line::END_ID()));
+ aLineEnd->setValue(aEndPoint->x(), aEndPoint->y());
+
+ aLineFeature->execute();
+ std::string aName = theEllipseFeature->name() + "_" +
+ (theStartPoint == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ? "major_axis" : "minor_axis");
+ aLineFeature->data()->setName(aName);
+ aLineFeature->lastResult()->data()->setName(aName);
+
+ createConstraintAttrAttr(aSketch,
+ SketchPlugin_ConstraintCoincidenceInternal::ID(), aStartPoint, aLineStart);
+ createConstraintAttrAttr(aSketch,
+ SketchPlugin_ConstraintCoincidenceInternal::ID(), aEndPoint, aLineEnd);
+}
+
GeomPnt2dPtr flyoutPointCoordinates(const ConstraintPtr& theConstraint)
{
// currently process Length constraints only
}
} // namespace SketchPlugin_Tools
+
+
+// =================================================================================================
+// namespace SketchPlugin_SegmentationTools
+// =================================================================================================
+
+void SketchPlugin_SegmentationTools::getFeaturePoints(const FeaturePtr& theFeature,
+ AttributePoint2DPtr& theStartPointAttr,
+ AttributePoint2DPtr& theEndPointAttr)
+{
+ std::string aFeatureKind = theFeature->getKind();
+ std::string aStartAttributeName, anEndAttributeName;
+ if (aFeatureKind == SketchPlugin_Line::ID()) {
+ aStartAttributeName = SketchPlugin_Line::START_ID();
+ anEndAttributeName = SketchPlugin_Line::END_ID();
+ }
+ else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+ aStartAttributeName = SketchPlugin_Arc::START_ID();
+ anEndAttributeName = SketchPlugin_Arc::END_ID();
+ }
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID()) {
+ aStartAttributeName = SketchPlugin_EllipticArc::START_POINT_ID();
+ anEndAttributeName = SketchPlugin_EllipticArc::END_POINT_ID();
+ }
+ if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
+ theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(aStartAttributeName));
+ theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(anEndAttributeName));
+ }
+}
+
+
+void SketchPlugin_SegmentationTools::getRefAttributes(
+ const FeaturePtr& theFeature,
+ std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
+ std::list<AttributePtr>& theRefsToFeature)
+{
+ theRefs.clear();
+
+ std::list<AttributePtr> aPointAttributes =
+ theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::set<AttributePtr> aPointAttributesSet;
+
+ std::list<AttributePtr>::const_iterator aPIt =
+ aPointAttributes.begin(), aPLast = aPointAttributes.end();
+ for (; aPIt != aPLast; aPIt++)
+ aPointAttributesSet.insert(*aPIt);
+
+ std::set<AttributePtr> aRefsAttributes = theFeature->lastResult()->data()->refsToMe();
+ std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
+ aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
+
+ std::set<AttributePtr>::const_iterator aIt;
+ for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
+ AttributePtr anAttr = (*aIt);
+ FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
+ if (!anAttrFeature->isMacro() && // <- skip reference from Trim or Split feature
+ anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
+ if (!aRefAttr->isObject()) { // find attributes referenced to feature point attributes
+ AttributePtr anAttrInRef = aRefAttr->attr();
+ if (anAttrInRef.get() &&
+ aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
+ if (theRefs.find(anAttrInRef) != theRefs.end())
+ theRefs[anAttrInRef].push_back(aRefAttr);
+ else {
+ std::list<AttributePtr> anAttrList;
+ anAttrList.push_back(aRefAttr);
+ theRefs[anAttrInRef] = anAttrList;
+ }
+ }
+ }
+ else { // find attributes referenced to feature itself
+ theRefsToFeature.push_back(anAttr);
+ }
+ }
+ }
+}
+
+GeomShapePtr SketchPlugin_SegmentationTools::getSubShape(
+ SketchPlugin_Feature* theFeature,
+ const std::string& theObjectAttributeId,
+ const std::string& thePointAttributeId,
+ std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
+ std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
+{
+ GeomShapePtr aBaseShape;
+
+ AttributeReferencePtr anObjectAttr = theFeature->reference(theObjectAttributeId);
+ ObjectPtr aBaseObject = anObjectAttr->value();
+ if (!aBaseObject.get())
+ return aBaseShape;
+
+ // point on feature
+ AttributePoint2DPtr aPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theFeature->attribute(thePointAttributeId));
+ std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
+ std::shared_ptr<GeomAPI_Pnt> anAttributePnt =
+ theFeature->sketch()->to3D(anAttributePnt2d->x(), anAttributePnt2d->y());
+
+ if (theCashedShapes.find(aBaseObject) == theCashedShapes.end())
+ fillObjectShapes(theFeature, aBaseObject, theCashedShapes, theObjectToPoints);
+
+ std::shared_ptr<GeomAPI_Pnt> aStartPoint;
+ std::shared_ptr<GeomAPI_Pnt> aSecondPoint;
+ const std::set<GeomShapePtr>& aShapes = theCashedShapes[aBaseObject];
+ std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
+ for (; anIt != aLast; anIt++) {
+ GeomShapePtr aCurrentShape = *anIt;
+ std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
+ if (ModelGeomAlgo_Point2D::isPointOnEdge(aCurrentShape, anAttributePnt, aProjectedPoint)) {
+ if (theFeature->getKind() == SketchPlugin_Split::ID()) {
+ // for Split operation collect start and end points of the shape
+ if (aCurrentShape->shapeType() == GeomAPI_Shape::EDGE) {
+ std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aCurrentShape));
+ aStartPoint = anEdge->firstPoint();
+ aSecondPoint = anEdge->lastPoint();
+ }
+ }
+ else
+ aBaseShape = aCurrentShape;
+ break;
+ }
+ }
+
+ if (!aStartPoint.get() || !aSecondPoint.get())
+ return aBaseShape;
+
+ FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObject);
+ if (anObjectAttr->isInitialized() && aBaseFeature.get() && aPointAttr->isInitialized()) {
+ ResultPtr aResult = aBaseFeature->lastResult();
+ GeomShapePtr aResultShape = aResult->shape();
+ std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
+
+ aPoints.push_back(aStartPoint);
+ aPoints.push_back(aSecondPoint);
+
+ std::set<std::shared_ptr<GeomAPI_Shape> > aSplitShapes;
+ GeomAlgoAPI_ShapeTools::splitShape_p(aResultShape, aPoints, aSplitShapes);
+ aBaseShape = GeomAlgoAPI_ShapeTools::findShape(aPoints, aSplitShapes);
+ }
+ return aBaseShape;
+}
+
+void SketchPlugin_SegmentationTools::fillObjectShapes(
+ SketchPlugin_Feature* theOpFeature,
+ const ObjectPtr& theObject,
+ std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
+ std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints)
+{
+ SketchPlugin_Sketch* aSketch = theOpFeature->sketch();
+
+ GeomAlgoAPI_ShapeTools::PointToRefsMap aPoints;
+ std::set<GeomShapePtr> aShapes;
+
+ std::set<AttributePoint2DPtr > aRefAttributes;
+ // current feature
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+ std::set<ResultPtr> anEdgeShapes;
+ // edges on feature
+ ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
+ if (!anEdgeShapes.empty()) {
+ GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
+
+ // coincidences to the feature
+ ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
+ aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
+ // layed on feature coincidences to divide it on several shapes
+ std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
+ std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+ aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+ std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
+ std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+ std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
+
+ ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
+ aX->dir(), aY, aPoints);
+
+ if (theOpFeature->getKind() == SketchPlugin_Trim::ID()) {
+ // collect all intersection points with other edges for Trim operation only
+ std::list<FeaturePtr> aFeatures;
+ for (int i = 0; i < aSketch->numberOfSubs(); i++) {
+ FeaturePtr aFeature = aSketch->subFeature(i);
+ if (aFeature.get() && aFeature->getKind() != SketchPlugin_Projection::ID())
+ aFeatures.push_back(aFeature);
+ }
+ ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPoints);
+ }
+
+ if (!aPoints.empty())
+ GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
+ }
+ theObjectToPoints[theObject] = aPoints;
+ theCashedShapes[theObject] = aShapes;
+}
+
+void SketchPlugin_SegmentationTools::updateRefAttConstraints(
+ const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
+{
+#if defined DEBUG_SPLIT || defined DEBUG_TRIM
+ std::cout << "updateRefAttConstraints" << std::endl;
+#endif
+
+ std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
+ anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
+ for (; anIt != aLast; anIt++) {
+ AttributePtr anAttribute = anIt->first;
+ AttributePtr aNewAttribute = anIt->second;
+
+ // not found in references
+ if (!aNewAttribute.get() ||
+ theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
+ continue;
+ std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
+ std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
+ aRLast = aRefAttributes.end();
+
+ for (; aRefIt != aRLast; aRefIt++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
+ if (aRefAttr.get()) {
+ aRefAttr->setAttr(aNewAttribute);
+#ifdef DEBUG_SPLIT
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
+ std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
+#endif
+ }
+ }
+ }
+}
+
+void SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(
+ const std::set<FeaturePtr>& theFeaturesToUpdate)
+{
+ std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
+ aLast = theFeaturesToUpdate.end();
+ for (; anIt != aLast; anIt++) {
+ FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
+ std::string aRefFeatureKind = aRefFeature->getKind();
+ if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
+ std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
+ std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
+ if (aLenghtFeature.get()) {
+ std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
+ ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
+ double aValue;
+ if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
+ aValueAttr->setValue(aValue);
+ }
+ }
+ }
+}
+
+AISObjectPtr SketchPlugin_SegmentationTools::getAISObject(
+ AISObjectPtr thePrevious,
+ SketchPlugin_Feature* theOpFeature,
+ const std::string& thePreviewObjectAttrName,
+ const std::string& thePreviewPointAttrName,
+ const std::string& theSelectedObjectAttrName,
+ const std::string& theSelectedPointAttrName)
+{
+#if defined DEBUG_SPLIT || defined DEBUG_TRIM_METHODS
+ std::cout << "getAISObject: " << theOpFeature->data()->name() << std::endl;
+#endif
+
+ AISObjectPtr anAIS = thePrevious;
+
+ std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
+ std::map<ObjectPtr, std::set<GeomShapePtr> > aCashedShapes;
+ std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap> aObjectToPoints;
+ GeomShapePtr aPreviewShape = getSubShape(theOpFeature,
+ thePreviewObjectAttrName, thePreviewPointAttrName, aCashedShapes, aObjectToPoints);
+ if (aPreviewShape.get())
+ aShapes.push_back(aPreviewShape);
+ GeomShapePtr aSelectedShape = getSubShape(theOpFeature,
+ theSelectedObjectAttrName, theSelectedPointAttrName, aCashedShapes, aObjectToPoints);
+ if (aSelectedShape.get())
+ aShapes.push_back(aSelectedShape);
+
+ if (aShapes.empty())
+ return AISObjectPtr();
+
+ GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
+ if (!aBaseShape.get())
+ return AISObjectPtr();
+
+ if (aBaseShape.get()) {
+ if (!anAIS)
+ anAIS = AISObjectPtr(new GeomAPI_AISObject);
+ anAIS->createShape(aBaseShape);
+
+ std::vector<int> aColor;
+ aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
+ double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
+ int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
+ anAIS->setColor(aColor[0], aColor[1], aColor[2]);
+ // width when there is not base object should be extened in several points
+ // in order to see this preview over highlight
+ anAIS->setWidth(aWidth+4);
+ anAIS->setLineStyle(aLineStyle);
+ }
+ else
+ anAIS = AISObjectPtr();
+ return anAIS;
+}
+
+#define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
+
+FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
+ const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
+{
+ FeaturePtr aFeature;
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
+ SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
+ if (!aSketch || !theBaseFeature.get())
+ return aFeature;
+
+ aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
+
+ GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
+ GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
+
+ aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
+ theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
+ aFeature->execute(); // to obtain result
+
+ return aFeature;
+}
+
+struct ArcAttributes
+{
+ std::string myKind;
+ std::string myCenter;
+ std::string myFocus;
+ std::string myStart;
+ std::string myEnd;
+ std::string myReversed;
+
+ ArcAttributes() {}
+
+ ArcAttributes(const std::string& theKind) : myKind(theKind)
+ {
+ if (myKind == SketchPlugin_Arc::ID()) {
+ myCenter = SketchPlugin_Arc::CENTER_ID();
+ myStart = SketchPlugin_Arc::START_ID();
+ myEnd = SketchPlugin_Arc::END_ID();
+ myReversed = SketchPlugin_Arc::REVERSED_ID();
+ }
+ else if (myKind == SketchPlugin_Circle::ID()) {
+ myCenter = SketchPlugin_Circle::CENTER_ID();
+ }
+ else if (myKind == SketchPlugin_Ellipse::ID()) {
+ myCenter = SketchPlugin_Ellipse::CENTER_ID();
+ myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
+ }
+ else if (myKind == SketchPlugin_EllipticArc::ID()) {
+ myCenter = SketchPlugin_EllipticArc::CENTER_ID();
+ myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
+ myStart = SketchPlugin_EllipticArc::START_POINT_ID();
+ myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
+ myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
+ }
+ }
+};
+
+FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
+ const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
+{
+ FeaturePtr aFeature;
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
+ SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
+ if (!aSketch || !theBaseFeature.get())
+ return aFeature;
+
+ ArcAttributes aBaseAttrs(theBaseFeature->getKind());
+ ArcAttributes aTargetAttrs;
+ if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
+ aBaseAttrs.myKind == SketchPlugin_Circle::ID())
+ aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
+ else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
+ aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
+ aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
+
+ if (aTargetAttrs.myKind.empty())
+ return aFeature;
+
+ aFeature = aSketch->addFeature(aTargetAttrs.myKind);
+ // update fillet arc: make the arc correct for sure, so, it is not needed to process
+ // the "attribute updated"
+ // by arc; moreover, it may cause cyclicity in hte mechanism of updater
+ bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
+
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
+ GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
+ if (!aTargetAttrs.myFocus.empty()) {
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
+ GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
+ }
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
+
+ aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
+ theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
+
+ /// fill referersed state of created arc as it is on the base arc
+ bool aReversed = aBaseAttrs.myReversed.empty() ? false :
+ theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
+ aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
+
+ aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
+ aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
+
+ return aFeature;
+}
#include <ModelAPI_Feature.h>
#include <ModelAPI_Attribute.h>
#include <ModelAPI_AttributeRefAttr.h>
+#include <GeomAPI_Shape.h>
#include <GeomDataAPI_Point2D.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+#include <list>
+#include <map>
+
+class GeomAPI_AISObject;
class SketchPlugin_Constraint;
class SketchPlugin_Feature;
const ObjectPtr theObject,
const bool theIsCanBeTangent);
+/// Creates auxiliary point for ellipse and corresponding internal constraint.
+/// \param[in] theEllipse base ellipse feature
+/// \param[in] theAttrName name of the attribute of the ellipse,
+/// the new point should be constrained
+void createAuxiliaryPointOnEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theAttrName);
+
+/// Creates auxiliary axis for ellipse and corresponding internal constraints.
+/// \param[in] theEllipse base ellipse feature
+/// \param[in] theStartAttr name of the attribute of the ellipse, the line is started
+/// \param[in] theEndAttr name of the attribute of the ellipse, the line is ended
+void createAuxiliaryAxisOfEllipse(const FeaturePtr& theEllipseFeature,
+ const std::string& theStartAttr,
+ const std::string& theEndAttr);
+
/// Creates passing point or tangent curve basing on the given attributes are initialized.
/// \param[in] theRefAttr prefered attribute to be converted
/// \param[in] theDefaultAttr default attribute if theRefAttr is not initialized
GeomPnt2dPtr flyoutPointCoordinates(const std::shared_ptr<SketchPlugin_Constraint>& theConstraint);
}; // namespace SketchPlugin_Tools
+namespace SketchPlugin_SegmentationTools
+{
+ /// Returns geom point attribute of the feature bounds. It processes line or arc.
+ /// For circle/ellipse feature, the result attributes are null
+ /// \param theFeature a source feature
+ /// \param theStartPointAttr an out attribute to start point
+ /// \param theEndPointAttr an out attribute to end point
+ void getFeaturePoints(const FeaturePtr& theFeature,
+ std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
+ std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr);
+
+ /// Obtains references to feature point attributes and to feature,
+ /// e.g. for feature line: 1st container is
+ /// <1st line point, list<entity_a in distance, entity_b in parallel> >
+ /// <2nd line point, list<> >
+ /// for feature circle 2nd container is <entity_a in Radius, entity_b in equal, ...>
+ /// \param theFeature an investigated feature
+ /// \param theRefs a container of list of referenced attributes
+ /// \param theRefsToFeature references to the feature result
+ void getRefAttributes(const FeaturePtr& theFeature,
+ std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
+ std::list<AttributePtr>& theRefsToFeature);
+
+ /// Obtains a part of shape selected/highlighted in the viewer for Split/Trim operation
+ /// \param[in] theFeature Split/Trim feature
+ /// \param[in] theObjectAttributeId name of attribute containing selected object
+ /// \param[in] thePointAttributeId name of attribute containing point selected on the object
+ GeomShapePtr getSubShape(
+ SketchPlugin_Feature* theFeature,
+ const std::string& theObjectAttributeId,
+ const std::string& thePointAttributeId,
+ std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
+ std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints);
+
+ /// Fulfill an internal containers by shapes obtained from the parameter object
+ /// Shapes are results of Split/Trim operation by points coincident to shape of the object
+ /// \param theOpFeture an operation feature (Split/Trim)
+ /// \param theObject a source object (will be splitted)
+ void fillObjectShapes(
+ SketchPlugin_Feature* theOpFeature,
+ const ObjectPtr& theObject,
+ std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
+ std::map<ObjectPtr, GeomAlgoAPI_ShapeTools::PointToRefsMap>& theObjectToPoints);
+
+ /// AIS object for selected/highlighted part of splitting/triming feature
+ /// \param[in] thePrevious previous presentation
+ /// \param[in] theOpFeture an operation feature (Split/Trim)
+ std::shared_ptr<GeomAPI_AISObject> getAISObject(std::shared_ptr<GeomAPI_AISObject> thePrevious,
+ SketchPlugin_Feature* theOpFeature,
+ const std::string& thePreviewObjectAttrName,
+ const std::string& thePreviewPointAttrName,
+ const std::string& theSelectedObjectAttrName,
+ const std::string& theSelectedPointAttrName);
+
+ /// Move constraints from attribute of base feature to attribute after modification
+ /// \param theBaseRefAttributes container of references to the attributes of base feature
+ /// \param theModifiedAttributes container of attributes placed instead of base attributes
+ /// at the same place
+ void updateRefAttConstraints(
+ const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes);
+
+ /// Updates line length if it exist in the list
+ /// \param theFeaturesToUpdate a constraint index
+ void updateFeaturesAfterOperation(const std::set<FeaturePtr>& theFeaturesToUpdate);
+
+
+ /// Creates a line feature filled by center of base feature and given points
+ /// \param theBaseFeature another arc feature
+ /// \param theFirstAttribute an attribute with coordinates for the start point
+ /// \param theSecondAttribute an attribute with coordinates for the end point
+ FeaturePtr createLineFeature(const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
+
+ /// Creates a circular/elliptic arc feature filled by center
+ /// (or by center and focus for elliptic arc) of base feature and given points
+ /// \param theBaseFeature another circle or ellipse or circular/elliptic arc
+ /// \param theFirstAttribute an attribute with coordinates for the start point
+ /// \param theSecondAttribute an attribute with coordinates for the end point
+ FeaturePtr createArcFeature(
+ const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
+
+}; // namespace SketchPlugin_SegmentationTools
+
#endif // SKETCHPLUGIN_TOOLS_H_
\ No newline at end of file
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomAlgoAPI_ShapeTools.h>
-#include <GeomAlgoAPI_CompoundBuilder.h>
#include <ModelAPI_AttributeReference.h>
#include <ModelAPI_AttributeString.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintCollinear.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
#include <SketchPlugin_Point.h>
-#include <SketchPlugin_Projection.h>
-#include <SketchPlugin_Tools.h>
#include <ModelAPI_EventReentrantMessage.h>
std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
anAttributePnt2d->y());
- if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
- fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
+ if (myCashedShapes.find(aBaseObject) == myCashedShapes.end()) {
+ SketchPlugin_SegmentationTools::fillObjectShapes(
+ this, aBaseObject, myCashedShapes, myObjectToPoints);
+ }
const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
if (!aShapes.empty()) {
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
ObjectPtr aBaseObject = aBaseObjectAttr->value();
- if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
- fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
+ if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) {
+ SketchPlugin_SegmentationTools::fillObjectShapes(
+ this, aBaseObject, myCashedShapes, myObjectToPoints);
+ }
bool aFound = false;
- const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
- for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
+ const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
+ for (GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
aPointIt != aRefsMap.end() && !aFound; aPointIt++) {
if (aPointIt->first->isEqual(thePoint)) {
const std::pair<std::list<AttributePoint2DPtr >,
// find references(attributes and features) to the base feature
std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
std::list<AttributePtr> aRefsToFeature;
- getRefAttributes(aBaseFeature, aBaseRefAttributes, aRefsToFeature);
+ SketchPlugin_SegmentationTools::getRefAttributes(
+ aBaseFeature, aBaseRefAttributes, aRefsToFeature);
#ifdef DEBUG_TRIM
std::cout << "---- getRefAttributes ----" << std::endl;
std::map<AttributePtr, std::list<AttributePtr> >::const_iterator
std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
const std::string& aKind = aBaseFeature->getKind();
FeaturePtr aReplacingFeature, aNewFeature;
- if (aKind == SketchPlugin_Circle::ID()) {
- aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d,
+ if (aKind == SketchPlugin_Circle::ID() ||
+ aKind == SketchPlugin_Ellipse::ID()) {
+ aReplacingFeature = trimClosed(aStartShapePoint2d, aLastShapePoint2d,
aFurtherCoincidences, aModifiedAttributes);
aFeaturesToDelete.insert(aBaseFeature);
aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
aFurtherCoincidences, aModifiedAttributes);
}
+ else if (aKind == SketchPlugin_EllipticArc::ID()) {
+ aNewFeature = trimEllipticArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
+ aFurtherCoincidences, aModifiedAttributes);
+ }
restoreCurrentFeature();
// constraints to end points of trim feature
- if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end())
- fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
+ if (myObjectToPoints.find(aBaseObject) == myObjectToPoints.end()) {
+ SketchPlugin_SegmentationTools::fillObjectShapes(
+ this, aBaseObject, myCashedShapes, myObjectToPoints);
+ }
// create coincidence to objects, intersected the base object
- const PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
+ const GeomAlgoAPI_ShapeTools::PointToRefsMap& aRefsMap = myObjectToPoints.at(aBaseObject);
for (std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
aLast = aFurtherCoincidences.end();
anIt != aLast; anIt++) {
continue;
std::pair<std::list<AttributePoint2DPtr >, std::list<ObjectPtr > > anInfo;
- for (PointToRefsMap::const_iterator aRefIt = aRefsMap.begin(); aRefIt != aRefsMap.end();
- aRefIt++)
+ for (GeomAlgoAPI_ShapeTools::PointToRefsMap::const_iterator aRefIt = aRefsMap.begin();
+ aRefIt != aRefsMap.end(); aRefIt++)
{
if (aRefIt->first->isEqual(aPoint)) {
anInfo = aRefIt->second;
ResultPtr aReplacingResult;
if (aReplacingFeature.get()) {
aReplacingFeature->execute(); // need it to obtain result
- aReplacingResult = getFeatureResult(aReplacingFeature);
+ aReplacingResult = aReplacingFeature->lastResult();
}
for(std::list<AttributePtr>::const_iterator anIt = aRefsToFeature.begin(),
aLast = aRefsToFeature.end();
}
}
- updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes, aFeaturesToDelete);
+ SketchPlugin_SegmentationTools::updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
// Wait all constraints being created, then send update events
static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
- updateFeaturesAfterTrim(aFeaturesToUpdate);
+ SketchPlugin_SegmentationTools::updateFeaturesAfterOperation(aFeaturesToUpdate);
// Send events to update the sub-features by the solver.
if(isUpdateFlushed) {
aPreviewObject = ObjectPtr();
aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
- aBaseObject = getFeatureResult(aBaseFeature);
+ aBaseObject = aBaseFeature->lastResult();
std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
aPreviewPnt2d->y());
ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
aPreviewObject = aBaseResult;
}
if (!aPreviewObject.get() && aNewFeature.get()) {
- ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
+ ResultPtr aNewFeatureResult = aNewFeature->lastResult();
if (aNewFeatureResult.get()) {
GeomShapePtr aShape = aNewFeatureResult->shape();
std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
std::shared_ptr<GeomAPI_Pnt2d> aPoint = aMessage->clickedPoint();
if (anObject.get() && aPoint.get()) {
- if (myCashedShapes.find(anObject) == myCashedShapes.end())
- fillObjectShapes(anObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
+ if (myCashedShapes.find(anObject) == myCashedShapes.end()) {
+ SketchPlugin_SegmentationTools::fillObjectShapes(
+ this, anObject, myCashedShapes, myObjectToPoints);
+ }
const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
if (aShapes.size() > 1) {
std::shared_ptr<ModelAPI_AttributeReference> aRefSelectedAttr =
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
- GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
+ GeomShapePtr aSelectedShape = SketchPlugin_SegmentationTools::getSubShape(this,
+ SELECTED_OBJECT(), SELECTED_POINT(), myCashedShapes, myObjectToPoints);
#ifdef DEBUG_TRIM_METHODS
if (!aSelectedShape.get())
std::cout << "Set empty selected object" << std::endl;
// get shape of the feature of the attribute
FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aRefAttr->object());
anAttributeFeature->execute(); // the modified value should be applyed to recompute shape
- PointToRefsMap aPointToAttributeOrObject;
+ GeomAlgoAPI_ShapeTools::PointToRefsMap aPointToAttributeOrObject;
std::list<FeaturePtr> aFeatures;
aFeatures.push_back(anAttributeFeature);
ModelGeomAlgo_Point2D::getPointsIntersectedShape(aTangentFeature, aFeatures,
AISObjectPtr SketchPlugin_Trim::getAISObject(AISObjectPtr thePrevious)
{
-#ifdef DEBUG_TRIM_METHODS
- std::cout << "SketchPlugin_Trim::getAISObject: " << data()->name() << std::endl;
-#endif
-
- AISObjectPtr anAIS = thePrevious;
-
- std::list<std::shared_ptr<GeomAPI_Shape> > aShapes;
- GeomShapePtr aPreviewShape = getSubShape(PREVIEW_OBJECT(), PREVIEW_POINT());
- if (aPreviewShape.get())
- aShapes.push_back(aPreviewShape);
- GeomShapePtr aSelectedShape = getSubShape(SELECTED_OBJECT(), SELECTED_POINT());
- if (aSelectedShape.get())
- aShapes.push_back(aSelectedShape);
-
- if (aShapes.empty())
- return AISObjectPtr();
-
- GeomShapePtr aBaseShape = GeomAlgoAPI_CompoundBuilder::compound(aShapes);
- if (!aBaseShape.get())
- return AISObjectPtr();
-
- if (aBaseShape.get()) {
- if (!anAIS)
- anAIS = AISObjectPtr(new GeomAPI_AISObject);
- anAIS->createShape(aBaseShape);
-
- std::vector<int> aColor;
- aColor = Config_PropManager::color("Visualization", "operation_remove_feature_color");
- double aWidth = SketchPlugin_SketchEntity::SKETCH_LINE_WIDTH();
- int aLineStyle = SketchPlugin_SketchEntity::SKETCH_LINE_STYLE();
- anAIS->setColor(aColor[0], aColor[1], aColor[2]);
- // width when there is not base object should be extened in several points
- // in order to see this preview over highlight
- anAIS->setWidth(aWidth+4);
- anAIS->setLineStyle(aLineStyle);
- }
- else
- anAIS = AISObjectPtr();
-
- return anAIS;
-}
-
-GeomShapePtr SketchPlugin_Trim::getSubShape(const std::string& theObjectAttributeId,
- const std::string& thePointAttributeId)
-{
- GeomShapePtr aBaseShape;
-
- AttributeReferencePtr anObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(theObjectAttributeId));
- ObjectPtr aBaseObject = anObjectAttr->value();
- if (!aBaseObject.get())
- return aBaseShape;
-
- // point on feature
- AttributePoint2DPtr aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- data()->attribute(thePointAttributeId));
- std::shared_ptr<GeomAPI_Pnt2d> anAttributePnt2d = aPointAttr->pnt();
- std::shared_ptr<GeomAPI_Pnt> anAttributePnt = sketch()->to3D(anAttributePnt2d->x(),
- anAttributePnt2d->y());
-
- if (myCashedShapes.find(aBaseObject) == myCashedShapes.end())
- fillObjectShapes(aBaseObject, sketch()->data()->owner(), myCashedShapes, myObjectToPoints);
-
- const std::set<GeomShapePtr>& aShapes = myCashedShapes[aBaseObject];
- if (!aShapes.empty()) {
- std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
- for (; anIt != aLast; anIt++) {
- GeomShapePtr aShape = *anIt;
- std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
- if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, anAttributePnt, aProjectedPoint))
- aBaseShape = aShape;
- }
- }
- return aBaseShape;
-}
-
-void SketchPlugin_Trim::getFeaturePoints(const FeaturePtr& theFeature,
- AttributePoint2DPtr& theStartPointAttr,
- AttributePoint2DPtr& theEndPointAttr)
-{
- std::string aFeatureKind = theFeature->getKind();
- std::string aStartAttributeName, anEndAttributeName;
- if (aFeatureKind == SketchPlugin_Line::ID()) {
- aStartAttributeName = SketchPlugin_Line::START_ID();
- anEndAttributeName = SketchPlugin_Line::END_ID();
- }
- else if (aFeatureKind == SketchPlugin_Arc::ID()) {
- aStartAttributeName = SketchPlugin_Arc::START_ID();
- anEndAttributeName = SketchPlugin_Arc::END_ID();
- }
- if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
- theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theFeature->attribute(aStartAttributeName));
- theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theFeature->attribute(anEndAttributeName));
- }
+ return SketchPlugin_SegmentationTools::getAISObject(thePrevious,
+ this, PREVIEW_OBJECT(), PREVIEW_POINT(), SELECTED_OBJECT(), SELECTED_POINT());
}
void SketchPlugin_Trim::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
+ ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
}
}
-void SketchPlugin_Trim::getRefAttributes(const FeaturePtr& theFeature,
- std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
- std::list<AttributePtr>& theRefsToFeature)
-{
- theRefs.clear();
-
- std::list<AttributePtr> aPointAttributes =
- theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::set<AttributePtr> aPointAttributesSet;
-
- std::list<AttributePtr>::const_iterator aPIt =
- aPointAttributes.begin(), aPLast = aPointAttributes.end();
- for (; aPIt != aPLast; aPIt++)
- aPointAttributesSet.insert(*aPIt);
-
- std::set<AttributePtr> aRefsAttributes = getFeatureResult(theFeature)->data()->refsToMe();
- std::set<AttributePtr> aFRefsList = theFeature->data()->refsToMe();
- aRefsAttributes.insert(aFRefsList.begin(), aFRefsList.end());
-
- std::set<AttributePtr>::const_iterator aIt;
- for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
- AttributePtr anAttr = (*aIt);
- FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
- if (anAttrFeature.get() != this &&
- anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
- if (!aRefAttr->isObject()) { /// find attributes referenced to feature point attributes
- AttributePtr anAttrInRef = aRefAttr->attr();
- if (anAttrInRef.get() &&
- aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
- if (theRefs.find(anAttrInRef) != theRefs.end())
- theRefs[anAttrInRef].push_back(aRefAttr);
- else {
- std::list<AttributePtr> anAttrList;
- anAttrList.push_back(aRefAttr);
- theRefs[anAttrInRef] = anAttrList;
- }
- }
- }
- else { /// find attributes referenced to feature itself
- theRefsToFeature.push_back(anAttr);
- }
- }
- }
-}
-
-void SketchPlugin_Trim::updateRefAttConstraints(
- const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
- const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes,
- std::set<FeaturePtr>& theFeaturesToDelete)
-{
-#ifdef DEBUG_TRIM
- std::cout << "SketchPlugin_Trim::updateRefAttConstraints" << std::endl;
-#endif
-
- std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
- anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
- for (; anIt != aLast; anIt++) {
- AttributePtr anAttribute = anIt->first;
-
- /// not found in references
- if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
- continue;
- std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
- std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
- aRLast = aRefAttributes.end();
-
- AttributePtr aNewAttribute = anIt->second;
- if (aNewAttribute.get()) {
- for (; aRefIt != aRLast; aRefIt++) {
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
- if (aRefAttr.get()) {
- aRefAttr->setAttr(aNewAttribute);
- }
- }
- }
- }
-}
-
void SketchPlugin_Trim::removeReferencesToAttribute(const AttributePtr& theAttribute,
std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes)
{
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
}
-void SketchPlugin_Trim::updateFeaturesAfterTrim(const std::set<FeaturePtr>& theFeaturesToUpdate)
-{
- std::set<FeaturePtr>::const_iterator anIt = theFeaturesToUpdate.begin(),
- aLast = theFeaturesToUpdate.end();
- for (; anIt != aLast; anIt++) {
- FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
- std::string aRefFeatureKind = aRefFeature->getKind();
- if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID()) {
- std::shared_ptr<SketchPlugin_ConstraintLength> aLenghtFeature =
- std::dynamic_pointer_cast<SketchPlugin_ConstraintLength>(*anIt);
- if (aLenghtFeature.get()) {
- std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(aLenghtFeature->attribute(SketchPlugin_Constraint::VALUE()));
- double aValue;
- if (aLenghtFeature->computeLenghtValue(aValue) && aValueAttr.get())
- aValueAttr->setValue(aValue);
- }
- }
- }
-}
-
FeaturePtr SketchPlugin_Trim::trimLine(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
/// points of trim
AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
- getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
std::shared_ptr<GeomAPI_Pnt2d> aStartFeaturePoint = aStartPointAttrOfBase->pnt();
std::shared_ptr<GeomAPI_Pnt2d> aLastFeaturePoint = anEndPointAttrOfBase->pnt();
// result is two lines: start line point - start shape point,
// last shape point - last line point
// create second line
- anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
+ anNewFeature = SketchPlugin_SegmentationTools::createLineFeature(
+ aBaseFeature, aLastShapePoint, aLastFeaturePoint);
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
(anNewFeature->attribute(SketchPlugin_Line::START_ID())));
// Collinear constraint for lines
SketchPlugin_Tools::createConstraintObjectObject(sketch(),
SketchPlugin_ConstraintCollinear::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(anNewFeature));
+ aBaseFeature->lastResult(),
+ anNewFeature->lastResult());
}
return anNewFeature;
}
/// points of trim
AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
- getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
else {
// result is two arcs: start arc point - start shape point, last shape point - last arc point
// create second arc
- anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
+ anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aLastShapePoint, aLastArcPoint);
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
(anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
// equal Radius constraint for arcs
SketchPlugin_Tools::createConstraintObjectObject(sketch(),
SketchPlugin_ConstraintEqual::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(anNewFeature));
+ aBaseFeature->lastResult(),
+ anNewFeature->lastResult());
// coincident centers constraint
SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
SketchPlugin_ConstraintCoincidence::ID(),
return anNewFeature;
}
-FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
- std::set<AttributePoint2DPtr>& thePoints,
+FeaturePtr SketchPlugin_Trim::trimEllipticArc(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ std::set<AttributePoint2DPtr>& thePoints,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
{
+ FeaturePtr anNewFeature;
// Check the base objects are initialized.
- AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
ObjectPtr aBaseObject = aBaseObjectAttr->value();
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- /// points of trim
- //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
- //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ // points of trim
+ AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+
+ std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
+
+ std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
+ std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
+ arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
+ aStartShapePoint, aLastShapePoint);
+#ifdef DEBUG_TRIM
+ std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
+ if (aStartShapePoint.get())
+ std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
+ aStartShapePoint->y() << "]" << std::endl;
+ std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " <<
+ aStartArcPoint->y() << "]" << std::endl;
+ if (aLastShapePoint.get())
+ std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " <<
+ aLastShapePoint->y() << "]" << std::endl;
+ std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " <<
+ aLastArcPoint->y() << "]" << std::endl;
+#endif
+
+ bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
+ bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
+ if (isStartPoint || isLastPoint) {
+ // result is one arc: changed existing arc
+ std::string aModifiedAttribute = isStartPoint ? SketchPlugin_EllipticArc::START_POINT_ID()
+ : SketchPlugin_EllipticArc::END_POINT_ID();
+ std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+ if (aStartShapePoint.get() && aLastShapePoint.get())
+ aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
+ else
+ aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
+
+ removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
+ theBaseRefAttributes);
+
+ fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aBaseFeature->attribute(aModifiedAttribute)));
+ }
+ else {
+ // result is two arcs: start arc point - start shape point, last shape point - last arc point
+ // create second arc
+ anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aLastShapePoint, aLastArcPoint);
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ anNewFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+
+ std::string aModifiedAttribute = SketchPlugin_EllipticArc::END_POINT_ID();
+ theModifiedAttributes.insert(
+ std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+
+ // modify base arc
+ fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
- /// trim feature
- FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aBaseFeature->attribute(aModifiedAttribute)));
+
+ // make elliptic arcs equal
+ SketchPlugin_Tools::createConstraintObjectObject(sketch(),
+ SketchPlugin_ConstraintEqual::ID(),
+ aBaseFeature->lastResult(),
+ anNewFeature->lastResult());
+ // coincident centers constraint
+ SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
+ SketchPlugin_ConstraintCoincidence::ID(),
+ aBaseFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
+
+#ifdef DEBUG_TRIM
+ std::cout << "Created arc on points:" << std::endl;
+ std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
+ aStartShapePoint->y() << "]" << std::endl;
+#endif
+ }
+ return anNewFeature;
+}
+
+FeaturePtr SketchPlugin_Trim::trimClosed(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
+{
+ // Check the base objects are initialized.
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
+ ObjectPtr aBaseObject = aBaseObjectAttr->value();
+ FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
+
+ // trim feature
+ FeaturePtr anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, theStartShapePoint, theLastShapePoint);
// arc created by trim of circle is always correct, that means that it is not inversed
- anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
+ const std::string& aReversedAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+ anNewFeature->boolean(aReversedAttrName)->setValue(false);
+
+ if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
+ theModifiedAttributes.insert(
+ std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
+ anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
+ }
+ else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
+
+ // update the PARENT_ID reference for all the features created by the ellipse
+ const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
+ std::list<AttributePtr> aRefsToParent;
+ for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
+ if ((*aRef)->id() == SketchPlugin_Line::PARENT_ID() ||
+ (*aRef)->id() == SketchPlugin_Point::PARENT_ID())
+ aRefsToParent.push_back(*aRef);
+ }
+ for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
+ aRef != aRefsToParent.end(); ++aRef)
+ std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(anNewFeature);
+ }
- theModifiedAttributes.insert(
- std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
- anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
+ const std::string& aStartAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
+ const std::string& aEndAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
+ (anNewFeature->attribute(aStartAttrName)));
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
+ (anNewFeature->attribute(aEndAttrName)));
return anNewFeature;
}
static const double anAngleTol = 1.e-12;
+ const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
+ const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+
std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
- bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+ theArc->attribute(aCenterAttrName))->pnt();
+ bool isReversed = theArc->boolean(aReversedAttrName)->value();
// collect directions to each point
std::shared_ptr<GeomAPI_Dir2d> aStartDir(
}
}
-
void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute,
const AttributePtr& theSourceAttribute)
{
aModifiedAttribute->setValue(aSourceAttribute->value());
}
}
-
-FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
-{
-#ifdef DEBUG_TRIM
- std::cout << "---- createLineFeature ---" << std::endl;
-#endif
-
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
-
- fillPointAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPoint);
- fillPointAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPoint);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- aFeature->execute(); // to obtain result
-
-#ifdef DEBUG_TRIM
- std::cout << "---- createLineFeature:end ---" << std::endl;
-#endif
-
- return aFeature;
-}
-
-FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
-{
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- std::string aCenterAttributeId;
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
- aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
- else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
- aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
-
- if (aCenterAttributeId.empty())
- return aFeature;
-
-#ifdef DEBUG_TRIM
- std::cout << "---- createArcFeature ---" << std::endl;
-#endif
-
- aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
- // update fillet arc: make the arc correct for sure, so, it is not needed to process
- // the "attribute updated"
- // by arc; moreover, it may cause cyclicity in hte mechanism of updater
- bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
-
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
- theBaseFeature->attribute(aCenterAttributeId));
- fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint);
- fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- /// fill referersed state of created arc as it is on the base arc
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
- bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
- aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
- }
- aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
- aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
-
- #ifdef DEBUG_TRIM
- std::cout << "---- createArcFeature:end ---" << std::endl;
- #endif
-
- return aFeature;
-}
-
-std::shared_ptr<ModelAPI_Result> SketchPlugin_Trim::getFeatureResult(
- const std::shared_ptr<ModelAPI_Feature>& theFeature)
-{
- std::shared_ptr<ModelAPI_Result> aResult;
-
- std::string aFeatureKind = theFeature->getKind();
- if (aFeatureKind == SketchPlugin_Line::ID())
- aResult = theFeature->firstResult();
- else if (aFeatureKind == SketchPlugin_Arc::ID())
- aResult = theFeature->lastResult();
- else if (aFeatureKind == SketchPlugin_Circle::ID())
- aResult = theFeature->lastResult();
-
- return aResult;
-}
-
-//********************************************************************
-void SketchPlugin_Trim::fillObjectShapes(const ObjectPtr& theObject,
- const ObjectPtr& theSketch,
- std::map<ObjectPtr, std::set<GeomShapePtr> >& theCashedShapes,
- std::map<ObjectPtr, PointToRefsMap>& theObjectToPoints)
-{
- PointToRefsMap aPointsInfo;
-
- std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
- std::map<std::shared_ptr<GeomAPI_Pnt>,
- std::list< AttributePoint2DPtr > > aPointToAttributes;
- std::map<std::shared_ptr<GeomAPI_Pnt>,
- std::list< ObjectPtr > > aPointToObjects;
-
- std::set<AttributePoint2DPtr > aRefAttributes;
- // current feature
- FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
- std::set<ResultPtr> anEdgeShapes;
- // edges on feature
- ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
- if (!anEdgeShapes.empty()) {
- GeomShapePtr aFeatureShape = (*anEdgeShapes.begin())->shape();
-
- // coincidences to the feature
- ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
- aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
- // layed on feature coincidences to divide it on several shapes
- std::shared_ptr<ModelAPI_Data> aData = theSketch->data();
- std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
- aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aData->attribute(SketchPlugin_Sketch::NORM_ID()));
- std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
-
- ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
- aX->dir(), aY, aPointsInfo);
-
- std::list<FeaturePtr> aFeatures;
- CompositeFeaturePtr aSketchComposite =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theSketch);
- for (int i = 0; i < aSketchComposite->numberOfSubs(); i++) {
- FeaturePtr aFeature = aSketchComposite->subFeature(i);
- if (aFeature.get() && aFeature->getKind() != SketchPlugin_Projection::ID())
- aFeatures.push_back(aFeature);
- }
- ModelGeomAlgo_Point2D::getPointsIntersectedShape(aFeature, aFeatures, aPointsInfo);
-
- GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPointsInfo, aShapes);
- }
- theObjectToPoints[theObject] = aPointsInfo;
- theCashedShapes[theObject] = aShapes;
-}
#define SketchPlugin_Trim_H_
#include "SketchPlugin.h"
+#include <SketchPlugin_Tools.h>
-#include "GeomAPI_IPresentable.h"
+#include <GeomAPI_IPresentable.h>
#include <ModelAPI_IReentrant.h>
#include <SketchPlugin_Sketch.h>
/// Apply information of the message to current object. It fills selected point and object
virtual std::string processEvent(const std::shared_ptr<Events_Message>& theMessage);
- typedef std::map<std::shared_ptr<GeomAPI_Pnt>,
- std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
- std::list<std::shared_ptr<ModelAPI_Object> > > > PointToRefsMap;
-
- static void fillObjectShapes(const std::shared_ptr<ModelAPI_Object>& theObject,
- const std::shared_ptr<ModelAPI_Object>& theSketch,
- std::map<std::shared_ptr<ModelAPI_Object>, std::set<GeomShapePtr> >& theCashedShapes,
- std::map<std::shared_ptr<ModelAPI_Object>, PointToRefsMap>& theObjectToPoints);
-
private:
bool setCoincidenceToAttribute(const AttributePtr& theAttribute,
const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
/// \param theFeature a feature that can be set into the attribute
bool moveTangency(const AttributePtr& theAttribute, const FeaturePtr& theFeature);
- GeomShapePtr getSubShape(const std::string& theObjectAttributeId,
- const std::string& thePointAttributeId);
-
- /// Returns geom point attribute of the feature bounds. It processes line or arc.
- /// For circle feature, the result attributes are null
- /// \param theFeature a source feature
- /// \param theStartPointAttr an out attribute to start point
- /// \param theStartPointAttr an out attribute to end point
- void getFeaturePoints(const FeaturePtr& theFeature,
- std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
- std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr);
-
/// Obtains those constraints of the feature that should be modified. output maps contain
/// point of coincidence and attribute id to be modified after split
/// \param theFeaturesToDelete [out] constrains that will be deleted after split
void getConstraints(std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToDelete,
std::set<FeaturePtr>& theFeaturesToUpdate);
- /// Obtains references to feature point attributes and to feature,
- /// e.g. for feature line: 1st container is
- /// <1st line point, list<entity_a in distance, entity_b in parallel> >
- /// <2nd line point, list<> >
- /// for feature circle 2nd container is <entity_a in Radius, entity_b in equal, ...>
- /// \param theFeature an investigated feature
- /// \param theRefs a container of list of referenced attributes
- void getRefAttributes(const FeaturePtr& theFeature,
- std::map<AttributePtr, std::list<AttributePtr> >& theRefs,
- std::list<AttributePtr>& theRefsToFeature);
-
- /// Move constraints from attribute of base feature to attribute after modification
- /// \param theBaseRefAttributes container of references to the attributes of base feature
- /// \param theModifiedAttributes container of attributes placed instead of base attributes
- /// at the same place
- void updateRefAttConstraints(
- const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
- const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes,
- std::set<std::shared_ptr<ModelAPI_Feature>>& theFeaturesToDelete);
-
/// Remove references constraints from attribute of base feature refer to the given attribute
/// \param theAttribute an attribute
/// \param theModifiedAttributes modifiable container of attributes
void removeReferencesToAttribute(const AttributePtr& theAttribute,
std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes);
- /// Updates line length if it exist in the list
- /// \param theFeaturesToUpdate a constraints container
- void updateFeaturesAfterTrim(const std::set<FeaturePtr>& theFeaturesToUpdate);
-
/// Make the base object is splitted by the point attributes
/// \param theBaseRefAttributes container of references to the attributes of base feature
/// \param thePoints a list of points where coincidences will be build
/// Make the base object is splitted by the point attributes
/// \param thePoints a list of points where coincidences will be build
- FeaturePtr trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
- std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
- std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+ /// \return new elliptic arc if it was created
+ FeaturePtr trimEllipticArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+
+ /// Make the base object is splitted by the point attributes
+ /// \param thePoints a list of points where coincidences will be build
+ FeaturePtr trimClosed(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
/// Correct the first and the second point to provide condition that the first is closer to
/// the start point and the second point - to the last end of current segment. To rearrange
void fillPointAttribute(const AttributePtr& theModifiedAttribute,
const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
- /// Creates a line feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createLineFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
-
- /// Creates an arc feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
-
- /// Result result of the feature to build constraint with. For arc, circle it is an edge result.
- /// \param theFeature a feature
- /// \return result object
- std::shared_ptr<ModelAPI_Result> getFeatureResult(
- const std::shared_ptr<ModelAPI_Feature>& theFeature);
-
private:
void findShapePoints(const std::string& theObjectAttributeId,
const std::string& thePointAttributeId,
private:
std::map<std::shared_ptr<ModelAPI_Object>, std::set<GeomShapePtr> > myCashedShapes;
- std::map<std::shared_ptr<ModelAPI_Object>, PointToRefsMap> myObjectToPoints;
+ std::map<std::shared_ptr<ModelAPI_Object>,
+ GeomAlgoAPI_ShapeTools::PointToRefsMap> myObjectToPoints;
};
#endif
#include "SketchPlugin_ConstraintDistance.h"
#include "SketchPlugin_ConstraintRigid.h"
#include "SketchPlugin_ConstraintTangent.h"
+#include "SketchPlugin_Ellipse.h"
+#include "SketchPlugin_EllipticArc.h"
#include "SketchPlugin_Fillet.h"
#include "SketchPlugin_Line.h"
#include "SketchPlugin_MacroArc.h"
#include <GeomAPI_Circ.h>
#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Ellipse.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Vertex.h>
if (!aOtherFea)
return true;
- if (aRefFea->getKind() == SketchPlugin_Line::ID()) {
- if (aOtherFea->getKind() != SketchPlugin_Arc::ID() &&
- aOtherFea->getKind() != SketchPlugin_Circle::ID()) {
- theError = "It refers to a %1, but %2 is neither an %3 nor %4";
- theError.arg(SketchPlugin_Line::ID()).arg(aParamA)
- .arg(SketchPlugin_Arc::ID()).arg(SketchPlugin_Circle::ID());
- return false;
- }
- }
- else if (aRefFea->getKind() == SketchPlugin_Arc::ID() ||
- aRefFea->getKind() == SketchPlugin_Circle::ID()) {
- if (aOtherFea->getKind() != SketchPlugin_Line::ID() &&
- aOtherFea->getKind() != SketchPlugin_Arc::ID() &&
- aOtherFea->getKind() != SketchPlugin_Circle::ID()) {
- theError = "It refers to an %1, but %2 is not a %3 or an %4 or a %5";
- theError.arg(SketchPlugin_Arc::ID()).arg(aParamA)
- .arg(SketchPlugin_Line::ID()).arg(SketchPlugin_Arc::ID())
- .arg(SketchPlugin_Circle::ID());
- return false;
- }
- }
- else {
- theError = "It refers to %1, but should refer to %2 or %3 or %4";
- theError.arg(aRefFea->getKind()).arg(SketchPlugin_Line::ID())
- .arg(SketchPlugin_Arc::ID()).arg(SketchPlugin_Circle::ID());
+ if (aRefFea->getKind() == SketchPlugin_Line::ID() &&
+ aOtherFea->getKind() == SketchPlugin_Line::ID()) {
+ theError = "Two segments cannot be tangent";
return false;
}
return true;
return true;
}
+bool SketchPlugin_PerpendicularAttrValidator::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
+ theError = "The attribute with the %1 type is not processed";
+ theError.arg(theAttribute->attributeType());
+ return false;
+ }
+
+ std::string aParamA = theArguments.front();
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+
+ FeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeRefAttrPtr aRefAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+
+ bool isObject = aRefAttr->isObject();
+ ObjectPtr anObject = aRefAttr->object();
+ if (isObject && anObject.get()) {
+ FeaturePtr aRefFea = ModelAPI_Feature::feature(anObject);
+
+ AttributeRefAttrPtr aOtherAttr = anOwner->refattr(aParamA);
+ ObjectPtr aOtherObject = aOtherAttr->object();
+ FeaturePtr aOtherFea = ModelAPI_Feature::feature(aOtherObject);
+ if (!aOtherFea)
+ return true;
+
+ // at least one feature should be a line
+ if (aRefFea->getKind() != SketchPlugin_Line::ID() &&
+ aOtherFea->getKind() != SketchPlugin_Line::ID()) {
+ theError = "At least one feature should be a line";
+ return false;
+ }
+ }
+ else {
+ theError = "It uses an empty object";
+ return false;
+ }
+
+ return true;
+}
+
bool SketchPlugin_NotFixedValidator::isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const
aType[i] = aFeature->getKind();
if (aFeature->getKind() != SketchPlugin_Line::ID() &&
aFeature->getKind() != SketchPlugin_Circle::ID() &&
- aFeature->getKind() != SketchPlugin_Arc::ID()) {
- theError = "The %1 feature kind of attribute is wrong. It should be %2 or %3 or %4";
- theError.arg(aFeature->getKind()).arg(SketchPlugin_Line::ID())
- .arg(SketchPlugin_Circle::ID()).arg(SketchPlugin_Arc::ID());
+ aFeature->getKind() != SketchPlugin_Arc::ID() &&
+ aFeature->getKind() != SketchPlugin_Ellipse::ID() &&
+ aFeature->getKind() != SketchPlugin_EllipticArc::ID()) {
+ theError = "The %1 feature is not supported by the Equal constraint.";
+ theError.arg(aFeature->getKind());
// wrong type of attribute
return false;
}
}
- if ((aType[0] == SketchPlugin_Line::ID() || aType[1] == SketchPlugin_Line::ID()) &&
- aType[0] != aType[1]) {
- theError = "Feature with kinds %1 and %2 can not be equal.";
+ bool isOk = aType[0] == aType[1];
+ if (!isOk) {
+ // circle and arc may be equal
+ isOk = (aType[0] == SketchPlugin_Arc::ID() && aType[1] == SketchPlugin_Circle::ID())
+ || (aType[0] == SketchPlugin_Circle::ID() && aType[1] == SketchPlugin_Arc::ID());
+ }
+ if (!isOk) {
+ // ellipse and elliptic arc may be equal
+ isOk = (aType[0] == SketchPlugin_EllipticArc::ID() && aType[1] == SketchPlugin_Ellipse::ID())
+ || (aType[0] == SketchPlugin_Ellipse::ID() && aType[1] == SketchPlugin_EllipticArc::ID());
+ }
+ if (!isOk) {
+ theError = "Features with kinds %1 and %2 can not be equal.";
theError.arg(aType[0]).arg(aType[1]);
return false;
}
}
if(!aConstraintCoincidence.get()) {
- theError = "Error: one of the selected point does not have coicidence.";
+ theError = "Error: one of the selected point does not have coincidence.";
return false;
}
if (aFeature->getKind() == SketchPlugin_Point::ID())
++aNbPoints;
- else if (aFeature->getKind() == SketchPlugin_Line::ID())
+ else if (aFeature->getKind() == SketchPlugin_Line::ID() ||
+ aFeature->getKind() == SketchPlugin_Arc::ID() ||
+ aFeature->getKind() == SketchPlugin_EllipticArc::ID())
++aNbLines;
}
}
theError.arg(theAttribute->attributeType());
return false;
}
+ FeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeStringPtr anArcTypeAttr = anOwner->string(SketchPlugin_MacroArc::ARC_TYPE());
+ if (anArcTypeAttr && anArcTypeAttr->value() != SketchPlugin_MacroArc::ARC_TYPE_BY_TANGENT_EDGE())
+ return true; // not applicable for non-tangent arcs
+
AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
AttributePtr anAttr = aRefAttr->attr();
if (!anAttr) {
return true;
}
+bool SketchPlugin_ArcTransversalPointValidator::isValid(
+ const AttributePtr& theAttribute,
+ const std::list<std::string>& /*theArguments*/,
+ Events_InfoMessage& theError) const
+{
+ if (theAttribute->attributeType() != ModelAPI_AttributeRefAttr::typeId()) {
+ theError = "The attribute with the %1 type is not processed";
+ theError.arg(theAttribute->attributeType());
+ return false;
+ }
+ FeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeStringPtr anArcTypeAttr = anOwner->string(SketchPlugin_MacroArc::ARC_TYPE());
+ if (anArcTypeAttr &&
+ anArcTypeAttr->value() != SketchPlugin_MacroArc::ARC_TYPE_BY_TRANSVERSAL_LINE())
+ return true; // not applicable for non-transversal arcs
+
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
+ AttributePtr anAttr = aRefAttr->attr();
+ if (!anAttr) {
+ theError = "The attribute %1 should be a point";
+ theError.arg(theAttribute->id());
+ return false;
+ }
+
+ FeaturePtr anAttrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
+ const std::string& aFeatureType = anAttrFeature->getKind();
+ if (aFeatureType == SketchPlugin_Line::ID()) {
+ // selected point should be bound point of line
+ const std::string& aPntId = anAttr->id();
+ if (aPntId != SketchPlugin_Line::START_ID() && aPntId != SketchPlugin_Line::END_ID()) {
+ theError = "The attribute %1 is not supported";
+ theError.arg(aPntId);
+ return false;
+ }
+ }
+ else {
+ theError = "Unable to build perpendicular arc on %1";
+ theError.arg(anAttrFeature->getKind());
+ return false;
+ }
+
+ return true;
+}
+
bool SketchPlugin_IntersectionValidator::isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const
if (!anAttrFeature)
return aValid;
- std::string aKind = anAttrFeature->getKind();
- if (aKind == SketchPlugin_Line::ID() ||
- aKind == SketchPlugin_Arc::ID() ||
- aKind == SketchPlugin_Circle::ID()) {
-
- std::set<ResultPtr> anEdgeShapes;
- ModelGeomAlgo_Shape::shapesOfType(anAttrFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
- if (anEdgeShapes.empty() || anEdgeShapes.size() > 1 /*there case has not existed yet*/)
- return aValid;
-
- // coincidences to the feature
- std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
- ModelGeomAlgo_Point2D::getPointsOfReference(anAttrFeature,
- SketchPlugin_ConstraintCoincidence::ID(),
- aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
-
- GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape();
- std::shared_ptr<SketchPlugin_Feature> aSFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttrFeature);
- SketchPlugin_Sketch* aSketch = aSFeature->sketch();
-
- std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
- std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
- aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
- std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aData->attribute(SketchPlugin_Sketch::NORM_ID()));
- std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
-
- typedef std::map<std::shared_ptr<GeomAPI_Pnt>,
- std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
- std::list<std::shared_ptr<ModelAPI_Object> > > > PointToRefsMap;
- PointToRefsMap aPointsInfo;
-
- ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(),
- aX->dir(), aDirY, aPointsInfo);
- int aCoincidentToFeature = (int)aPointsInfo.size();
- if (aKind == SketchPlugin_Circle::ID())
- aValid = aCoincidentToFeature >= 2;
- else
- aValid = aCoincidentToFeature >= 1;
- }
+ std::set<ResultPtr> anEdgeShapes;
+ ModelGeomAlgo_Shape::shapesOfType(anAttrFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
+ if (anEdgeShapes.empty() || anEdgeShapes.size() > 1 /*there case has not existed yet*/)
+ return aValid;
+
+ // coincidences to the feature
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
+ ModelGeomAlgo_Point2D::getPointsOfReference(anAttrFeature,
+ SketchPlugin_ConstraintCoincidence::ID(),
+ aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
+
+ GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape();
+ std::shared_ptr<SketchPlugin_Feature> aSFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttrFeature);
+ if (!aSFeature)
+ return false;
+ SketchPlugin_Sketch* aSketch = aSFeature->sketch();
+
+ std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
+ std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+ aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+ std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
+ std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+ std::shared_ptr<GeomAPI_Dir> aDirY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
+
+ typedef std::map<std::shared_ptr<GeomAPI_Pnt>,
+ std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
+ std::list<std::shared_ptr<ModelAPI_Object> > > > PointToRefsMap;
+ PointToRefsMap aPointsInfo;
+
+ ModelGeomAlgo_Point2D::getPointsInsideShape(anAttrShape, aRefAttributes, aC->pnt(),
+ aX->dir(), aDirY, aPointsInfo);
+ int aCoincidentToFeature = (int)aPointsInfo.size();
+ if (anAttrFeature->getKind() == SketchPlugin_Circle::ID() ||
+ anAttrFeature->getKind() == SketchPlugin_Ellipse::ID())
+ aValid = aCoincidentToFeature >= 2;
+ else
+ aValid = aCoincidentToFeature >= 1;
return aValid;
}
if (!aSketchFeature.get() || aSketchFeature->isCopy())
return aValid;
- std::string aKind = aBaseFeature->getKind();
- if (aKind != SketchPlugin_Line::ID() &&
- aKind != SketchPlugin_Arc::ID() &&
- aKind != SketchPlugin_Circle::ID())
- return aValid;
-
// point on feature
AttributePoint2DPtr aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
aTrimFeature->data()->attribute(SketchPlugin_Trim::PREVIEW_POINT()));
std::map<ObjectPtr, std::map<std::shared_ptr<GeomAPI_Pnt>,
std::pair<std::list<std::shared_ptr<GeomDataAPI_Point2D> >,
std::list<std::shared_ptr<ModelAPI_Object> > > > > anObjectToPoints;
- SketchPlugin_Trim::fillObjectShapes(aBaseObject, aSketch->data()->owner(),
- aCashedShapes, anObjectToPoints);
+ SketchPlugin_SegmentationTools::fillObjectShapes(
+ aTrimFeature.get(), aBaseObject, aCashedShapes, anObjectToPoints);
const std::set<GeomShapePtr>& aShapes = aCashedShapes[aBaseObject];
return aShapes.size() > 1;
double aDot = fabs(aNormal->dot(aLineDir));
bool aValid = fabs(aDot - 1.0) >= tolerance * tolerance;
if (!aValid)
- theError = "Error: Edge is already in the sketch plane.";
+ theError = "Error: Line is orthogonal to the sketch plane.";
return aValid;
}
else if (anEdge->isCircle() || anEdge->isArc()) {
std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
std::shared_ptr<GeomAPI_Dir> aCircNormal = aCircle->normal();
double aDot = fabs(aNormal->dot(aCircNormal));
- bool aValid = fabs(aDot - 1.0) < tolerance * tolerance;
+ bool aValid = aDot >= tolerance * tolerance;
+ if (!aValid)
+ theError.arg(anEdge->isCircle() ? "Error: Circle is orthogonal to the sketch plane."
+ : "Error: Arc is orthogonal to the sketch plane.");
+ return aValid;
+ }
+ else if (anEdge->isEllipse()) {
+ std::shared_ptr<GeomAPI_Ellipse> anEllipse = anEdge->ellipse();
+ std::shared_ptr<GeomAPI_Dir> anEllipseNormal = anEllipse->normal();
+ double aDot = fabs(aNormal->dot(anEllipseNormal));
+ bool aValid = fabs(aDot - 1.0) <= tolerance * tolerance;
if (!aValid)
- theError.arg(anEdge->isCircle() ? "Error: Cirlce is already in the sketch plane."
- : "Error: Arc is already in the sketch plane.");
+ theError.arg(anEdge->isClosed() ? "Error: Ellipse is orthogonal to the sketch plane."
+ : "Error: Elliptic Arc is orthogonal to the sketch plane.");
return aValid;
}
- theError = "Error: Selected object is not line, circle or arc.";
+ theError = "Error: Selected object is not supported for projection.";
return false;
}
Events_InfoMessage& theError) const;
};
+/**\class SketchPlugin_PerpendicularAttrValidator
+ * \ingroup Validators
+ * \brief Validator for the perpendicular constraint input.
+ *
+ * Checks that two arcs are not selected for perpendicular.
+ */
+class SketchPlugin_PerpendicularAttrValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute
+ //! \param theError error message
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
/**\class SketchPlugin_NotFixedValidator
* \ingroup Validators
Events_InfoMessage& theError) const;
};
+/**\class SketchPlugin_ArcTransversalPointValidator
+ * \ingroup Validators
+ * \brief Validator for the point where the transversal arc is building.
+ *
+ * Checks that the point is a start or end point just on line or arc.
+ */
+class SketchPlugin_ArcTransversalPointValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute
+ //! \param theError error message
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
+
/**\class SketchPlugin_SplitValidator
* \ingroup Validators
* \brief Validator for the entity of the following type:
<context>
<name>Sketch:Model_FeatureValidator</name>
<message>
- <source>Attribute "DirX" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select a plane for the sketch</translation>
</message>
</context>
<context>
<name>Sketch:Model_FeatureValidator</name>
<message>
- <source>Attribute "Features" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Sketch objects are not defined</translation>
</message>
</context>
<context>
<name>Sketch:Model_FeatureValidator</name>
<message>
- <source>Attribute "External" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select the sketch plane</translation>
</message>
</context>
<context>
<name>Sketch:Model_FeatureValidator</name>
<message>
- <source>Attribute "SolverDOF" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Can not compute degrees of freedom</translation>
</message>
</context>
<context>
<name>Sketch:Model_FeatureValidator</name>
<message>
- <source>Attribute "SolverError" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Can not compute the solver error</translation>
</message>
</context>
+ <context>
+ <name>SketchMacroCircle:center_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a point in the viewer</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a point in the viewer</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroCircle:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a point in the viewer</translation>
+ </message>
+ </context>
<context>
<name>SketchMacroCircle:CircleRadius:GeomValidators_Positive</name>
<message>
<context>
<name>SketchMacroCircle:Model_FeatureValidator</name>
<message>
- <source>Attribute "circle_center" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>A center point is not selected</translation>
</message>
</context>
<context>
<name>SketchMacroCircle:Model_FeatureValidator</name>
<message>
- <source>Attribute "FirstPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>A first point is not selected</translation>
</message>
</context>
<context>
<name>SketchMacroCircle:Model_FeatureValidator</name>
<message>
- <source>Attribute "SecondPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>A second point is not selected</translation>
</message>
</context>
<context>
<name>SketchMacroCircle:Model_FeatureValidator</name>
<message>
- <source>Attribute "ThirdPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>A third point is not selected</translation>
</message>
</context>
<context>
<name>SketchMacroCircle:Model_FeatureValidator</name>
<message>
- <source>Attribute "circle_radius" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the circle radius</translation>
</message>
</context>
+
+ <context>
+ <name>SketchMacroArc:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:center_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a center point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_1</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an end point in the viewer.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_2</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an end point in the viewer.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:end_point_3</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an end point in the viewer.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select an end point in the viewer.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an passed point in the viewer.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_1</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a start point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroArc:start_point_2</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a start point.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroEllipse:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:first_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a first point in the viewer.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:passed_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a passed point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipse:second_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a second point.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchMacroEllipticArc:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:center</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a point.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a center point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:end_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an end point.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select an end point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchMacroEllipticArc:major_axis_point</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a major axis point.</translation>
+ </message>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a major axis point.</translation>
+ </message>
+ </context>
+
+ <context>
+ <name>SketchSplit:Model_FeatureValidator</name>
+ <message>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a segment to split in the viewer.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchSplit:SelectedObject:SketchPlugin_SplitValidator</name>
+ <message>
+ <source>Select a segment to split in the viewer.</source>
+ <translation></translation>
+ </message>
+ </context>
<context>
<name>SketchConstraintHorizontal:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintPerpendicular:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintPerpendicular:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintRadius:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Circle is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintRadius:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintValue" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the radius</translation>
</message>
</context>
<context>
<name>SketchConstraintVertical:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Line is not selected</translation>
</message>
</context>
<context>
<name>SketchLine:Model_FeatureValidator</name>
<message>
- <source>Attribute "EndPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>End point is not selected</translation>
</message>
</context>
<context>
<name>SketchLine:EndPoint</name>
<message>
- <source>Attribute "EndPoint" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select an end point in the viewer</translation>
</message>
</context>
<context>
<name>SketchLine:StartPoint</name>
<message>
- <source>Attribute "StartPoint" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select a start point in the viewer</translation>
</message>
</context>
<context>
<name>SketchLine:StartPoint</name>
<message>
- <source>Attribute "StartPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Start point is not selected</translation>
</message>
</context>
<context>
<name>SketchLine:EndPoint</name>
<message>
- <source>Attribute "EndPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>End point is not selected</translation>
</message>
</context>
<context>
<name>SketchLine:Model_FeatureValidator</name>
<message>
- <source>Attribute "StartPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select a start point</translation>
</message>
</context>
<context>
<name>SketchPoint:Model_FeatureValidator</name>
<message>
- <source>Attribute "PointCoordinates" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Point is not defined</translation>
</message>
</context>
<context>
<name>SketchPoint:PointCoordinates</name>
<message>
- <source>Attribute "PointCoordinates" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a point</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchPoint:PointCoordinates</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select a point</translation>
</message>
</context>
<context>
<name>SketchRectangle:RectEndPoint</name>
<message>
- <source>Attribute "RectEndPoint" is locked by modification value in the viewer.</source>
- <translation>Select an end point of the rectangle</translation>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an end point of the rectangle.</translation>
</message>
</context>
<context>
<name>SketchRectangle:RectStartPoint</name>
<message>
- <source>Attribute "RectStartPoint" is locked by modification value in the viewer.</source>
- <translation>Select a first point of the rectangle</translation>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a point.</translation>
</message>
</context>
<context>
<name>SketchRectangle:Model_FeatureValidator</name>
<message>
- <source>Attribute "RectStartPoint" is not initialized.</source>
- <translation>Select a first point of the rectangle</translation>
+ <source>Attribute "%1" is not initialized.</source>
+ <translation>Select a point.</translation>
</message>
</context>
<context>
- <name>SketchRectangle:Model_FeatureValidator</name>
+ <name>SketchRectangle:RectEndPoint</name>
<message>
- <source>Attribute "RectEndPoint" is not initialized.</source>
- <translation>Select an end point of the rectangle</translation>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select a point.</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchRectangle:RectStartPoint</name>
+ <message>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
+ <translation>Select an point.</translation>
</message>
</context>
<context>
<name>SketchArc:ArcCenter</name>
<message>
- <source>Attribute "center_point" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select a center point</translation>
</message>
</context>
<context>
<name>SketchArc:ArcCenter</name>
<message>
- <source>Attribute "center_point" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Center point is not defined</translation>
</message>
</context>
<context>
<name>SketchArc:ArcEndPoint</name>
<message>
- <source>Attribute "ArcEndPoint" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select an end point</translation>
</message>
</context>
<context>
<name>SketchArc:ArcPassedPoint</name>
<message>
- <source>Attribute "ArcPassedPoint" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select an intermediate point</translation>
</message>
</context>
<context>
<name>SketchArc:ArcStartPoint</name>
<message>
- <source>Attribute "ArcStartPoint" is locked by modification value in the viewer.</source>
+ <source>Attribute "%1" is locked by modification value in the viewer.</source>
<translation>Select a start point</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator</name>
<message>
- <source>Attribute "ArcEndPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>End point is not defined</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator</name>
<message>
- <source>Attribute "ArcPassedPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Intermediate point is not defined</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator</name>
<message>
- <source>Attribute "center_point" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select an arc center</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator:ArcStartPoint</name>
<message>
- <source>Attribute "start_point" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select an arc start point</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator</name>
<message>
- <source>Attribute "end_point" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select an arc end point</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator</name>
<message>
- <source>Attribute "ArcPassedPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select an arc passed point</translation>
</message>
</context>
<context>
<name>SketchArc:Model_FeatureValidator</name>
<message>
- <source>Attribute "ArcTangentPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select an arc tangent point</translation>
</message>
</context>
<context>
<name>SketchConstraintMirror:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Mirror line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintMirror:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintMirrorList" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Objects for mirror are not selected</translation>
</message>
</context>
<context>
<name>SketchMultiRotation:Model_FeatureValidator</name>
<message>
- <source>Attribute "AngleType" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Type of angle is not defined</translation>
</message>
</context>
<context>
<name>SketchMultiRotation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiRotationCenter" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Rotation center is not selected</translation>
</message>
</context>
<context>
<name>SketchMultiRotation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiRotationList" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select objects to rotate</translation>
</message>
</context>
<context>
<name>SketchMultiRotation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiRotationAngle" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set rotation angle</translation>
</message>
</context>
<context>
<name>SketchMultiRotation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiRotationObjects" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the number of resulting objects</translation>
</message>
</context>
<context>
<name>SketchMultiTranslation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiTranslationEndPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>End point of translation vector is not defined</translation>
</message>
</context>
<context>
<name>SketchMultiTranslation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiTranslationList" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Objects for translation are not selected</translation>
</message>
</context>
<context>
<name>SketchMultiTranslation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiTranslationStartPoint" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select a start point</translation>
</message>
</context>
<context>
<name>SketchMultiTranslation:Model_FeatureValidator</name>
<message>
- <source>Attribute "MultiTranslationObjects" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select a total number of objects</translation>
</message>
</context>
<context>
<name>SketchConstraintAngle:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintAngle:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintAngle:Model_FeatureValidator</name>
<message>
- <source>Attribute "AngleValue" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the angle value</translation>
</message>
</context>
<context>
<name>SketchConstraintAngle:Model_FeatureValidator</name>
<message>
- <source>Attribute "AngleType" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Type of angle is not set</translation>
</message>
</context>
<name>SketchConstraintCoincidence:ConstraintEntityA:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<name>SketchConstraintCoincidence:ConstraintEntityB:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<name>SketchConstraintCoincidence:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintCoincidence:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintDistance:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintDistance:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintDistance:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintDistance:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintDistance:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintValue" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the distance</translation>
</message>
</context>
<name>SketchConstraintEqual:ConstraintEntityA:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<name>SketchConstraintEqual:ConstraintEntityB:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<source>An empty object is used.</source>
<translation>An empty object is used</translation>
</message>
+ <message>
+ <source>The %1 feature is not supported by the Equal constraint.</source>
+ <translation>The %1 feature is not supported by the Equal constraint.</translation>
+ </message>
+ <message>
+ <source>Features with kinds %1 and %2 can not be equal.</source>
+ <translation>Features with kinds %1 and %2 can not be equal.</translation>
+ </message>
</context>
<context>
<name>SketchConstraintEqual:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintEqual:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintLength:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintLength:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintLength:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintValue" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the length value</translation>
</message>
</context>
<name>SketchConstraintMiddle:ConstraintEntityA:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<name>SketchConstraintMiddle:ConstraintEntityB:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<context>
<name>SketchConstraintMiddle:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintMiddle:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintParallel:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintParallel:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second line is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintRigid:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Object is not selected</translation>
</message>
</context>
<name>SketchConstraintTangent:ConstraintEntityA:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityA and ConstraintEntityB attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
</message>
</context>
<context>
<name>SketchConstraintTangent:ConstraintEntityB:PartSet_DifferentObjects</name>
<message>
<source>The feature uses one object in ConstraintEntityB and ConstraintEntityA attributes.</source>
- <translation>Diferent objects should be selected</translation>
+ <translation>Different objects should be selected</translation>
+ </message>
+ </context>
+ <context>
+ <name>SketchConstraintTangent:ConstraintEntityA:SketchPlugin_TangentAttr</name>
+ <message>
+ <source>Two segments cannot be tangent</source>
+ <translation>Two segments cannot be tangent</translation>
</message>
</context>
<context>
<context>
<name>SketchConstraintTangent:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>First object is not selected</translation>
</message>
</context>
<context>
<name>SketchConstraintTangent:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityB" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Second object is not selected</translation>
</message>
</context>
<context>
<name>SketchFillet:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintEntityA" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Select one or several points for filet</translation>
</message>
</context>
<context>
<name>SketchFillet:Model_FeatureValidator</name>
<message>
- <source>Attribute "ConstraintValue" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation>Set the fillet radius</translation>
</message>
</context>
<context>
<name>SketchFillet:ConstraintEntityA:SketchPlugin_FilletVertexValidator</name>
<message>
- <source>Error: one of the selected point does not have coicidence.</source>
- <translation>One of the selected point does not have coicidence</translation>
+ <source>Error: one of the selected point does not have coincidence.</source>
+ <translation>One of the selected point does not have coincidence</translation>
</message>
</context>
<context>
<source>The attribute with the %1 type is not processed</source>
<translation>An argument of type %1 of the projection feature is not supported</translation>
</message>
- </context>
- <context>
- <name>SketchProjection:ExternalFeature:SketchPlugin_ProjectionValidator</name>
<message>
- <source>The attribute %1 should be an edge</source>
- <translation>The projected item must be an edge</translation>
+ <source>The attribute %1 should be an edge or vertex</source>
+ <translation>The projected item must be an edge or a vertex</translation>
</message>
- </context>
- <context>
- <name>SketchProjection:ExternalFeature:SketchPlugin_ProjectionValidator</name>
<message>
<source>There is no sketch referring to the current feature</source>
<translation>The projection feature has no sketch</translation>
</message>
+ <message>
+ <source>Unable to project feature from the same sketch</source>
+ <translation>Feature from the current sketch cannot be projected</translation>
+ </message>
+ <message>
+ <source>Error: Line is orthogonal to the sketch plane.</source>
+ <translation>Error: Line is orthogonal to the sketch plane.</translation>
+ </message>
+ <message>
+ <source>Error: Circle is orthogonal to the sketch plane.</source>
+ <translation>Error: Circle is orthogonal to the sketch plane.</translation>
+ </message>
+ <message>
+ <source>Error: Arc is orthogonal to the sketch plane.</source>
+ <translation>Error: Arc is orthogonal to the sketch plane.</translation>
+ </message>
+ <message>
+ <source>Error: Ellipse is orthogonal to the sketch plane.</source>
+ <translation>Error: Ellipse is orthogonal to the sketch plane.</translation>
+ </message>
+ <message>
+ <source>Error: Elliptic Arc is orthogonal to the sketch plane.</source>
+ <translation>Error: Elliptic Arc is orthogonal to the sketch plane.</translation>
+ </message>
+ <message>
+ <source>Error: Selected object is not supported for projection.</source>
+ <translation>Error: Selected object is not supported for projection.</translation>
+ </message>
</context>
-
<context>
<name>SketchProjection:Model_FeatureValidator</name>
<message>
- <source>Attribute "ExternalFeature" is not initialized.</source>
+ <source>Attribute "%1" is not initialized.</source>
<translation></translation>
</message>
</context>
--- /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
+#
+
+"""
+ Test3019.py
+ Test case for issue #3019 "Error when load python script"
+"""
+
+from salome.shaper import model
+from SketchAPI import *
+from GeomAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+model.addParameter(Part_1_doc, "k", "30")
+model.addParameter(Part_1_doc, "M", "10")
+model.addParameter(Part_1_doc, "h", "20")
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(15, -8.660254037843767, 15, 8.660254037843762)
+SketchLine_2 = Sketch_1.addLine(15, 8.660254037843762, 0, 0)
+SketchLine_2.setAuxiliary(True)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_1.addLine(0, 0, 15, -8.660254037843767)
+SketchLine_3.setAuxiliary(True)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchLine_2.result(), SketchLine_1.result())
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchLine_3.result(), SketchLine_1.result())
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchAPI_Point(SketchPoint_1).coordinates(), SketchLine_3.startPoint())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_3.startPoint(), SketchLine_1.result(), "k/2", True)
+SketchMultiRotation_1 = Sketch_1.addRotation([SketchLine_1.result()], SketchLine_3.startPoint(), 360, 6, True)
+[SketchLine_4, SketchLine_5, SketchLine_6, SketchLine_7, SketchLine_8] = SketchMultiRotation_1.rotated()
+SketchCircle_1 = Sketch_1.addCircle(0, 0, 10)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], "M")
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_3.startPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_4f-SketchLine_5f-SketchLine_6f-SketchLine_7f-SketchLine_8f-SketchCircle_1_2r")], model.selection(), "h", 0)
+Point_2 = model.addPoint(Part_1_doc, "0", "0", "h/2")
+Sphere_1 = model.addSphere(Part_1_doc, model.selection("VERTEX", "Point_1"), 19.5)
+Common_1 = model.addCommon(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Sphere_1_1")])
+Folder_1 = model.addFolder(Part_1_doc, Sketch_1, Extrusion_1)
+Folder_2 = model.addFolder(Part_1_doc, Point_2, Sphere_1)
+model.end()
+
+model.testNbResults(Common_1, 1)
+model.testNbSubResults(Common_1, [0])
+model.testNbSubShapes(Common_1, GeomAPI_Shape.SOLID, [1])
+model.testNbSubShapes(Common_1, GeomAPI_Shape.FACE, [21])
+model.testNbSubShapes(Common_1, GeomAPI_Shape.EDGE, [114])
+model.testNbSubShapes(Common_1, GeomAPI_Shape.VERTEX, [228])
+model.testResultsVolumes(Common_1, [9302.86764641653])
+
+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
+
+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("XOZ"))
+SketchCircle_1 = Sketch_1.addCircle(-29.162567194092, -4.973946236013575, 24.14811574522286)
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_2.addLine(-77.4631035991525, 93.73498685458384, -26.22597517262966, 46.04636096467877)
+SketchLine_2 = Sketch_2.addLine(-26.22597517262966, 46.04636096467877, 72.15826607546271, 123.5085570887089)
+SketchConstraintCoincidence_1 = Sketch_2.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchLine_3 = Sketch_2.addLine(72.15826607546271, 123.5085570887089, -77.4631035991525, 93.73498685458384)
+SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchLine_1.startPoint(), SketchLine_3.endPoint())
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f")], model.selection(), 50, 50)
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_2/SketchLine_2"))
+SketchProjection_1 = Sketch_3.addProjection(model.selection("EDGE", "Sketch_1/SketchCircle_1_2"), True)
+SketchEllipse_1 = SketchProjection_1.createdFeature()
+SketchLine_4 = Sketch_3.addLine(-38.4752072906812, 8.839586602068252, -81.23746009846235, -13.43622256955389)
+SketchConstraintCoincidence_4 = Sketch_3.setCoincident(SketchLine_4.startPoint(), SketchEllipse_1.result())
+SketchLine_5 = Sketch_3.addLine(-81.23746009846235, -13.43622256955389, -38.77350759536917, -18.22647561616226)
+SketchConstraintCoincidence_5 = Sketch_3.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint())
+SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchEllipse_1.result())
+model.do()
+model.end()
+
+model.checkSketch(Sketch_3, 4)
+model.testNbSubFeatures(Sketch_3, "SketchConstraintCoincidence", 3)
+ellipse1 = SketchEllipse_1.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse1.isEdge() and ellipse1.edge().isEllipse())
+
+model.begin()
+Sketch_3.setPlane(model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_2/SketchLine_1"))
+model.end()
+model.checkSketch(Sketch_3, 4)
+model.testNbSubFeatures(Sketch_3, "SketchConstraintCoincidence", 3)
+ellipse1 = SketchEllipse_1.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse1.isEdge() and ellipse1.edge().isEllipse())
+
+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 constraint "Angle" applied for ellipse's axes
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestAngleEllipse(unittest.TestCase):
+ def setUp(self):
+ axisStart = GeomAPI_Pnt2d(30., 60.)
+ axisEnd = GeomAPI_Pnt2d(80., 50.)
+ passedPoint = GeomAPI_Pnt2d(60., 60.)
+ self.myAngle = 60
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+ self.myDOF = 5
+ self.myOX = self.mySketch.addLine("OX")
+ model.do()
+ self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ self.myCenter = macroEllipse.center()
+ self.myFocus1 = macroEllipse.focus1()
+ self.myFocus2 = macroEllipse.focus2()
+ self.myMajorAxis = macroEllipse.majorAxis()
+ self.myMajorStart = macroEllipse.majorAxisStart()
+ self.myMajorEnd = macroEllipse.majorAxisEnd()
+ self.myMinorAxis = macroEllipse.minorAxis()
+ self.myMinorStart = macroEllipse.minorAxisStart()
+ self.myMinorEnd = macroEllipse.minorAxisEnd()
+
+
+ def tearDown(self):
+ model.end()
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+ def assertAngle(self, theStart, theEnd, theAngle):
+ dirX = (theEnd.x() - theStart.x()) / math.hypot(theEnd.x() - theStart.x(), theEnd.y() - theStart.y())
+ self.assertAlmostEqual(math.fabs(dirX), math.cos(theAngle * math.pi / 180))
+
+
+ def test_angle_major_axis(self):
+ """ Test 1. Make angle between major axis of ellipse and OX
+ """
+ self.mySketch.setAngle(self.myOX.result(), self.myMajorAxis.result(), self.myAngle)
+ self.myDOF -= 1
+ model.do()
+ self.assertAngle(self.myMajorAxis.startPoint(), self.myMajorAxis.endPoint(), self.myAngle)
+ self.assertAngle(self.myMajorStart.coordinates(), self.myMajorEnd.coordinates(), self.myAngle)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintAngle", 1)
+
+ def test_angle_minor_axis(self):
+ """ Test 2. Make angle between minor axis of ellipse and OX
+ """
+ self.mySketch.setAngle(self.myOX.result(), self.myMinorAxis.result(), self.myAngle)
+ self.myDOF -= 1
+ model.do()
+ self.assertAngle(self.myMinorAxis.startPoint(), self.myMinorAxis.endPoint(), self.myAngle)
+ self.assertAngle(self.myMinorStart.coordinates(), self.myMinorEnd.coordinates(), self.myAngle)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintAngle", 1)
+
+ def test_angle_ellipse_axes(self):
+ """ Test 3. Set angle between axes of an ellipse. Check conflicting constraints.
+ """
+ self.mySketch.setAngle(self.myMajorAxis.result(), self.myMinorAxis.result(), self.myAngle)
+ model.end()
+ self.assertNotEqual(self.mySketch.solverError(), "")
+ model.undo()
+ model.begin()
+
+
+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 constraint coincidence applied for ellipse and its sub-results
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestCoincidenceEllipse(unittest.TestCase):
+ def setUp(self):
+ axisStart = GeomAPI_Pnt2d(30., 60.)
+ axisEnd = GeomAPI_Pnt2d(80., 50.)
+ passedPoint = GeomAPI_Pnt2d(60., 60.)
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+ self.myDOF = 5
+ self.myOrigin = self.mySketch.addPoint("Origin")
+ self.myOX = self.mySketch.addLine("OX")
+ model.do()
+ self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ self.myCenter = macroEllipse.center()
+ self.myFocus1 = macroEllipse.focus1()
+ self.myFocus2 = macroEllipse.focus2()
+ self.myMajorAxis = macroEllipse.majorAxis()
+ self.myMajorStart = macroEllipse.majorAxisStart()
+ self.myMajorEnd = macroEllipse.majorAxisEnd()
+ self.myMinorAxis = macroEllipse.minorAxis()
+ self.myMinorStart = macroEllipse.minorAxisStart()
+ self.myMinorEnd = macroEllipse.minorAxisEnd()
+ self.myExpectFailure = False
+
+ def tearDown(self):
+ model.end()
+ if self.myExpectFailure:
+ assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+ model.undo()
+ else:
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointFixing(self, thePoint):
+ self.mySketch.setCoincident(thePoint, self.myOrigin.coordinates())
+ self.myDOF -= 2
+ model.do()
+ if not self.myExpectFailure:
+ self.assertPoints(thePoint, self.myOrigin.coordinates())
+ self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+ def checkPointOnAxis(self, thePoint):
+ self.mySketch.setCoincident(thePoint, self.myOX.result())
+ self.myDOF -= 1
+ model.do()
+ if not self.myExpectFailure:
+ self.assertAlmostEqual(thePoint.y(), 0.0)
+ self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+ def checkPointOnLine(self, thePoint, theLineStart, theLineEnd):
+ vecP = [thePoint.x() - theLineStart.x(), thePoint.y() - theLineStart.y()]
+ vecL = [theLineEnd.x() - theLineStart.x(), theLineEnd.y() - theLineStart.y()]
+ dist = math.fabs(vecP[0] * vecL[1] - vecP[1] * vecL[0]) / math.hypot(vecL[0], vecL[1])
+
+ self.assertAlmostEqual(dist, 0.0)
+ self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+ def checkPointOnEllipse(self, thePoint, theEllipse):
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, thePoint)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, thePoint)
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7)
+
+
+ def test_concident_center(self):
+ """ Test 1. Make center of ellipse coincident with the Origin
+ """
+ self.checkPointFixing(self.myCenter.coordinates())
+
+ def test_coincident_first_focus(self):
+ """ Test 2. Make first focus of ellipse coincident with the Origin
+ """
+ self.checkPointFixing(self.myFocus1.coordinates())
+
+ def test_coincident_second_focus(self):
+ """ Test 3. Make second focus of ellipse coincident with the Origin
+ """
+ self.checkPointFixing(self.myFocus2.coordinates())
+
+ def test_coincident_major_axis_start(self):
+ """ Test 4. Make start point on the major axis of ellipse coincident with the Origin
+ """
+ self.checkPointFixing(self.myMajorStart.coordinates())
+
+ def test_coincident_major_axis_end(self):
+ """ Test 5. Make end point on the major axis of ellipse coincident with the Origin
+ """
+ self.checkPointFixing(self.myMajorEnd.coordinates())
+
+ def test_coincident_minor_axis_start(self):
+ """ Test 6. Make start point on the minor axis of ellipse coincident with the Origin
+ """
+ self.checkPointFixing(self.myMinorStart.coordinates())
+
+ def test_coincident_minor_axis_end(self):
+ """ Test 7. Make end point on the minor axis of ellipse coincident with the Origin.
+ Check solver is failed to compute the coincidence.
+ """
+ self.myExpectFailure = True
+ self.checkPointFixing(self.myMinorEnd.coordinates())
+
+
+ def test_center_on_line(self):
+ """ Test 8. Make center of ellipse coincident with the OX
+ """
+ self.checkPointOnAxis(self.myCenter.coordinates())
+
+ def test_first_focus_on_line(self):
+ """ Test 9. Make first focus of ellipse coincident with the OX
+ """
+ self.checkPointOnAxis(self.myFocus1.coordinates())
+
+ def test_second_focus_on_line(self):
+ """ Test 10. Make second focus of ellipse coincident with the OX
+ """
+ self.checkPointOnAxis(self.myFocus2.coordinates())
+
+ def test_major_axis_start_on_line(self):
+ """ Test 11. Make start point on the major axis of ellipse coincident with the OX
+ """
+ self.checkPointOnAxis(self.myMajorStart.coordinates())
+
+ def test_major_axis_end_on_line(self):
+ """ Test 12. Make end point on the major axis of ellipse coincident with the OX
+ """
+ self.checkPointOnAxis(self.myMajorEnd.coordinates())
+
+ def test_minor_axis_start_on_line(self):
+ """ Test 13. Make start point on the minor axis of ellipse coincident with the OX
+ """
+ self.checkPointOnAxis(self.myMinorStart.coordinates())
+
+ def test_minor_axis_end_on_line(self):
+ """ Test 14. Make end point on the minor axis of ellipse coincident with the OX
+ """
+ self.myExpectFailure = True
+ self.checkPointOnAxis(self.myMinorEnd.coordinates())
+
+
+ def test_origin_on_major_axis(self):
+ """ Test 15. Make origin coincident with the major axis of the ellipse
+ """
+ self.mySketch.setCoincident(self.myMajorAxis.result(), self.myOrigin.coordinates())
+ self.myDOF -= 1
+ model.do()
+ self.checkPointOnLine(self.myOrigin.coordinates(), self.myMajorStart.coordinates(), self.myMajorEnd.coordinates())
+
+ def test_origin_on_minor_axis(self):
+ """ Test 16. Make origin coincident with the minor axis of the ellipse
+ """
+ self.mySketch.setCoincident(self.myMinorAxis.result(), self.myOrigin.coordinates())
+ self.myDOF -= 1
+ model.end()
+ # solver shows wrong result
+ assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+ model.undo()
+
+ # move ellipse and set coincidence once again
+ model.begin()
+ self.mySketch.move(self.myMinorStart, 20, 10)
+ model.do()
+ self.mySketch.setCoincident(self.myMinorAxis.results()[-1], self.myOrigin.coordinates())
+ model.do()
+ self.checkPointOnLine(self.myOrigin.coordinates(), self.myMinorStart.coordinates(), self.myMinorEnd.coordinates())
+
+
+ def test_origin_on_ellipse(self):
+ """ Test 17. Make origin coincident with the ellipse
+ """
+ self.mySketch.setCoincident(self.myEllipse.results()[-1], self.myOrigin.coordinates())
+ self.myDOF -= 1
+ model.do()
+ self.checkPointOnEllipse(self.myOrigin.coordinates(), self.myEllipse)
+
+
+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 constraint coincidence applied for elliptic arc and its sub-results
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-10-02"
+
+class TestCoincidenceEllipticArc(unittest.TestCase):
+ def setUp(self):
+ center = GeomAPI_Pnt2d(-10., 5.)
+ axisEnd = GeomAPI_Pnt2d(40., -5.)
+ startPoint = GeomAPI_Pnt2d(20., 5.)
+ endPoint = GeomAPI_Pnt2d(-40., 5.)
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipticArc = self.mySketch.addEllipticArc(center, axisEnd, startPoint, endPoint, False)
+ self.myDOF = 7
+ self.myOrigin = self.mySketch.addPoint("Origin")
+ self.myOX = self.mySketch.addLine("OX")
+ model.do()
+ self.myEllipticArc = SketchAPI_EllipticArc(model.lastSubFeature(self.mySketch, "SketchEllipticArc"))
+ self.myCenter = macroEllipticArc.center()
+ self.myFocus1 = macroEllipticArc.focus1()
+ self.myFocus2 = macroEllipticArc.focus2()
+ self.myMajorAxis = macroEllipticArc.majorAxis()
+ self.myMajorStart = macroEllipticArc.majorAxisStart()
+ self.myMajorEnd = macroEllipticArc.majorAxisEnd()
+ self.myMinorAxis = macroEllipticArc.minorAxis()
+ self.myMinorStart = macroEllipticArc.minorAxisStart()
+ self.myMinorEnd = macroEllipticArc.minorAxisEnd()
+ self.myExpectFailure = False
+
+ def tearDown(self):
+ model.end()
+ if self.myExpectFailure:
+ assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+ model.undo()
+ else:
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipticArc.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipticArc.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipticArc.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipticArc.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipticArc.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipticArc.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipticArc.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipticArc.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipticArc.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipticArc.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipticArc.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointFixing(self, thePoint):
+ self.mySketch.setCoincident(thePoint, self.myOrigin.coordinates())
+ self.myDOF -= 2
+ model.do()
+ if not self.myExpectFailure:
+ self.assertPoints(thePoint, self.myOrigin.coordinates())
+ self.assertGreater(self.myEllipticArc.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipticArc.minorRadius().value(), 0.0)
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+ def checkPointOnAxis(self, thePoint):
+ self.mySketch.setCoincident(thePoint, self.myOX.result())
+ self.myDOF -= 1
+ model.do()
+ if not self.myExpectFailure:
+ self.assertAlmostEqual(thePoint.y(), 0.0)
+ self.assertGreater(self.myEllipticArc.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipticArc.minorRadius().value(), 0.0)
+
+ def checkPointOnLine(self, thePoint, theLineStart, theLineEnd):
+ vecP = [thePoint.x() - theLineStart.x(), thePoint.y() - theLineStart.y()]
+ vecL = [theLineEnd.x() - theLineStart.x(), theLineEnd.y() - theLineStart.y()]
+ dist = math.fabs(vecP[0] * vecL[1] - vecP[1] * vecL[0]) / math.hypot(vecL[0], vecL[1])
+
+ self.assertAlmostEqual(dist, 0.0)
+ self.assertGreater(self.myEllipticArc.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipticArc.minorRadius().value(), 0.0)
+
+ def checkPointOnEllipse(self, thePoint, theEllipse):
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, thePoint)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, thePoint)
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7)
+
+
+ def test_concident_center(self):
+ """ Test 1. Make center of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myCenter.coordinates())
+
+ def test_coincident_first_focus(self):
+ """ Test 2. Make first focus of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myFocus1.coordinates())
+
+ def test_coincident_second_focus(self):
+ """ Test 3. Make second focus of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myFocus2.coordinates())
+
+ def test_coincident_major_axis_start(self):
+ """ Test 4. Make start point on the major axis of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myMajorStart.coordinates())
+
+ def test_coincident_major_axis_end(self):
+ """ Test 5. Make end point on the major axis of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myMajorEnd.coordinates())
+
+ def test_coincident_minor_axis_start(self):
+ """ Test 6. Make start point on the minor axis of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myMinorStart.coordinates())
+
+ def test_coincident_minor_axis_end(self):
+ """ Test 7. Make end point on the minor axis of elliptic arc coincident with the Origin.
+ Check solver is failed to compute the coincidence.
+ """
+ self.myExpectFailure = True
+ self.checkPointFixing(self.myMinorEnd.coordinates())
+
+ def test_coincident_start(self):
+ """ Test 8. Make start point of elliptic arc coincident with the Origin.
+ Check solver is failed to compute the coincidence.
+ """
+ self.myExpectFailure = True
+ self.checkPointFixing(self.myEllipticArc.startPoint())
+
+ def test_coincident_end(self):
+ """ Test 9. Make end point of elliptic arc coincident with the Origin
+ """
+ self.checkPointFixing(self.myEllipticArc.endPoint())
+
+
+ def test_center_on_line(self):
+ """ Test 10. Make center of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myCenter.coordinates())
+
+ def test_first_focus_on_line(self):
+ """ Test 11. Make first focus of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myFocus1.coordinates())
+
+ def test_second_focus_on_line(self):
+ """ Test 12. Make second focus of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myFocus2.coordinates())
+
+ def test_major_axis_start_on_line(self):
+ """ Test 13. Make start point on the major axis of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myMajorStart.coordinates())
+
+ def test_major_axis_end_on_line(self):
+ """ Test 14. Make end point on the major axis of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myMajorEnd.coordinates())
+
+ def test_minor_axis_start_on_line(self):
+ """ Test 15. Make start point on the minor axis of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myMinorStart.coordinates())
+
+ def test_minor_axis_end_on_line(self):
+ """ Test 16. Make end point on the minor axis of elliptic arc coincident with the OX
+ """
+ self.myExpectFailure = True
+ self.checkPointOnAxis(self.myMinorEnd.coordinates())
+
+ def test_coincident_start_on_line(self):
+ """ Test 17. Make start point of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myEllipticArc.startPoint())
+
+ def test_coincident_end_on_line(self):
+ """ Test 18. Make end point of elliptic arc coincident with the OX
+ """
+ self.checkPointOnAxis(self.myEllipticArc.endPoint())
+
+
+ def test_origin_on_major_axis(self):
+ """ Test 19. Make origin coincident with the major axis of the elliptic arc
+ """
+ self.mySketch.setCoincident(self.myMajorAxis.result(), self.myOrigin.coordinates())
+ self.myDOF -= 1
+ model.do()
+ self.checkPointOnLine(self.myOrigin.coordinates(), self.myMajorStart.coordinates(), self.myMajorEnd.coordinates())
+
+ def test_origin_on_minor_axis(self):
+ """ Test 20. Make origin coincident with the minor axis of the elliptic arc
+ """
+ self.mySketch.setCoincident(self.myMinorAxis.result(), self.myOrigin.coordinates())
+ self.myDOF -= 1
+ model.end()
+ # solver shows wrong result
+ assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+ model.undo()
+
+ # move elliptic arc and set coincidence once again
+ model.begin()
+ self.mySketch.move(self.myMinorStart, 20, 10)
+ model.do()
+ self.mySketch.setCoincident(self.myMinorAxis.results()[-1], self.myOrigin.coordinates())
+ model.do()
+ self.checkPointOnLine(self.myOrigin.coordinates(), self.myMinorStart.coordinates(), self.myMinorEnd.coordinates())
+
+
+ def test_origin_on_ellipse(self):
+ """ Test 21. Make origin coincident with the elliptic arc
+ """
+ self.mySketch.setCoincident(self.myEllipticArc.results()[-1], self.myOrigin.coordinates())
+ self.myDOF -= 1
+ model.do()
+ self.checkPointOnEllipse(self.myOrigin.coordinates(), self.myEllipticArc)
+
+
+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 constraint "Collinear" applied for ellipse's axes
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-18"
+
+class TestCollinearEllipse(unittest.TestCase):
+ def setUp(self):
+ axisStart = GeomAPI_Pnt2d(30., 60.)
+ axisEnd = GeomAPI_Pnt2d(80., 50.)
+ passedPoint = GeomAPI_Pnt2d(60., 60.)
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+ self.myDOF = 5
+ self.myOX = self.mySketch.addLine("OX")
+ model.do()
+ self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ self.myCenter = macroEllipse.center()
+ self.myFocus1 = macroEllipse.focus1()
+ self.myFocus2 = macroEllipse.focus2()
+ self.myMajorAxis = macroEllipse.majorAxis()
+ self.myMajorStart = macroEllipse.majorAxisStart()
+ self.myMajorEnd = macroEllipse.majorAxisEnd()
+ self.myMinorAxis = macroEllipse.minorAxis()
+ self.myMinorStart = macroEllipse.minorAxisStart()
+ self.myMinorEnd = macroEllipse.minorAxisEnd()
+
+
+ def tearDown(self):
+ model.end()
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+
+ def test_collinear_major_axis(self):
+ """ Test 1. Make major axis of ellipse collinear with OX
+ """
+ self.mySketch.setCollinear(self.myOX.result(), self.myMajorAxis.result())
+ self.myDOF -= 2
+ model.do()
+ self.assertAlmostEqual(self.myMajorAxis.startPoint().y(), 0)
+ self.assertAlmostEqual(self.myMajorAxis.endPoint().y(), 0)
+ self.assertAlmostEqual(self.myMajorStart.coordinates().y(), 0)
+ self.assertAlmostEqual(self.myMajorEnd.coordinates().y(), 0)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCollinear", 1)
+
+ def test_collinear_minor_axis(self):
+ """ Test 2. Make minor axis of ellipse collinear with OX
+ """
+ self.mySketch.setCollinear(self.myOX.result(), self.myMinorAxis.result())
+ self.myDOF -= 2
+ model.end()
+ # solver shows wrong result
+ assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+ model.undo()
+
+ model.begin()
+ self.mySketch.move(self.myMinorStart.coordinates(), 0, 70)
+ self.mySketch.move(self.myMinorEnd.coordinates(), 50, 70)
+ model.do()
+ self.mySketch.setCollinear(self.myOX.result(), self.myMinorAxis.result())
+ model.do()
+ self.assertAlmostEqual(self.myMinorAxis.startPoint().y(), 0)
+ self.assertAlmostEqual(self.myMinorAxis.endPoint().y(), 0)
+ self.assertAlmostEqual(self.myMinorStart.coordinates().y(), 0)
+ self.assertAlmostEqual(self.myMinorEnd.coordinates().y(), 0)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCollinear", 1)
+
+ def test_collinear_ellipse_axes(self):
+ """ Test 3. Set collinear axes of an ellipse. Check conflicting constraints.
+ """
+ self.mySketch.setCollinear(self.myMajorAxis, self.myMinorAxis)
+ model.end()
+ self.assertNotEqual(self.mySketch.solverError(), "")
+ model.undo()
+ model.begin()
+
+
+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 constraint "Distance" applied sub-elements of an ellipse
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestDistanceEllipse(unittest.TestCase):
+ def setUp(self):
+ axisStart = GeomAPI_Pnt2d(20., 60.)
+ axisEnd = GeomAPI_Pnt2d(80., 50.)
+ passedPoint = GeomAPI_Pnt2d(60., 70.)
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+ self.myDOF = 5
+ self.myOrigin = self.mySketch.addPoint("Origin")
+ self.myOX = self.mySketch.addLine("OX")
+ model.do()
+ self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ self.myCenter = macroEllipse.center()
+ self.myFocus1 = macroEllipse.focus1()
+ self.myFocus2 = macroEllipse.focus2()
+ self.myMajorAxis = macroEllipse.majorAxis()
+ self.myMajorStart = macroEllipse.majorAxisStart()
+ self.myMajorEnd = macroEllipse.majorAxisEnd()
+ self.myMinorAxis = macroEllipse.minorAxis()
+ self.myMinorStart = macroEllipse.minorAxisStart()
+ self.myMinorEnd = macroEllipse.minorAxisEnd()
+ self.myExpectFailure = False
+ self.myDistance = 20
+
+ def tearDown(self):
+ model.end()
+ if self.myExpectFailure:
+ assert(self.mySketch.solverError() != ""), "PlaneGCS limitation: if you see this message, then PlaneGCS has solved the set of constraints correctly"
+ model.undo()
+ else:
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 8)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", 11)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintDistance", 1)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointPointDistance(self, thePoint1, thePoint2):
+ self.mySketch.setDistance(thePoint1, thePoint2, self.myDistance)
+ self.myDOF -= 1
+ model.do()
+ if not self.myExpectFailure:
+ self.assertAlmostEqual(model.distancePointPoint(thePoint1, thePoint2), self.myDistance)
+ self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+ def checkPointLineDistance(self, thePoint, theLine):
+ self.mySketch.setDistance(thePoint, theLine.result(), self.myDistance)
+ self.myDOF -= 1
+ model.do()
+ self.assertAlmostEqual(model.distancePointLine(thePoint, theLine), self.myDistance)
+ self.assertGreater(self.myEllipse.majorRadius().value(), 0.0)
+ self.assertGreater(self.myEllipse.minorRadius().value(), 0.0)
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+
+ def test_distance_center(self):
+ """ Test 1. Set distance to the Origin from the center of ellipse
+ """
+ self.checkPointPointDistance(self.myCenter.coordinates(), self.myOrigin.coordinates())
+
+ def test_distance_first_focus(self):
+ """ Test 2. Set distance to the Origin from the first focus of ellipse
+ """
+ self.checkPointPointDistance(self.myFocus1.coordinates(), self.myOrigin.coordinates())
+
+ def test_distance_second_focus(self):
+ """ Test 3. Set distance to the Origin from the second focus of ellipse
+ """
+ self.checkPointPointDistance(self.myFocus2.coordinates(), self.myOrigin.coordinates())
+
+ def test_distance_major_axis_start(self):
+ """ Test 4. Set distance to the Origin from the start point on the major axis of ellipse
+ """
+ self.checkPointPointDistance(self.myMajorStart.coordinates(), self.myOrigin.coordinates())
+
+ def test_distance_major_axis_end(self):
+ """ Test 5. Set distance to the Origin from the end point on the major axis of ellipse
+ """
+ self.checkPointPointDistance(self.myMajorEnd.coordinates(), self.myOrigin.coordinates())
+
+ def test_distance_minor_axis_start(self):
+ """ Test 6. Set distance to the Origin from the start point on the minor axis of ellipse
+ """
+ self.checkPointPointDistance(self.myMinorStart.coordinates(), self.myOrigin.coordinates())
+
+ def test_distance_minor_axis_end(self):
+ """ Test 7. Set distance to the Origin from the end point on the minor axis of ellipse
+ """
+ self.myExpectFailure = True
+ self.checkPointPointDistance(self.myMinorEnd.coordinates(), self.myOrigin.coordinates())
+
+
+ def test_distance_center_to_line(self):
+ """ Test 8. Set distance from theOX to the center of ellipse
+ """
+ self.checkPointLineDistance(self.myCenter.coordinates(), self.myOX)
+
+ def test_distance_first_focus_to_line(self):
+ """ Test 9. Set distance from theOX to the first focus of ellipse
+ """
+ self.checkPointLineDistance(self.myFocus1.coordinates(), self.myOX)
+
+ def test_distance_second_focus_to_line(self):
+ """ Test 10. Set distance from theOX to the second focus of ellipse
+ """
+ self.checkPointLineDistance(self.myFocus2.coordinates(), self.myOX)
+
+ def test_distance_major_axis_start_to_line(self):
+ """ Test 11. Set distance from theOX to the start point on the major axis of ellipse
+ """
+ self.checkPointLineDistance(self.myMajorStart.coordinates(), self.myOX)
+
+ def test_distance_major_axis_end_to_line(self):
+ """ Test 12. Set distance from theOX to the end point on the major axis of ellipse
+ """
+ self.checkPointLineDistance(self.myMajorEnd.coordinates(), self.myOX)
+
+ def test_distance_minor_axis_start_to_line(self):
+ """ Test 13. Set distance from theOX to the start point on the minor axis of ellipse
+ """
+ self.checkPointLineDistance(self.myMinorStart.coordinates(), self.myOX)
+
+ def test_distance_minor_axis_end_to_line(self):
+ """ Test 14. Set distance from theOX to the end point on the minor axis of ellipse
+ """
+ self.myDistance = 150
+ self.checkPointLineDistance(self.myMinorEnd.coordinates(), self.myOX)
+
+
+ def test_distance_origin_to_major_axis(self):
+ """ Test 15. Set distance from the Origin to the major axis of the ellipse
+ """
+ self.checkPointLineDistance(self.myOrigin.coordinates(), self.myMajorAxis)
+
+ def test_distance_origin_to_minor_axis(self):
+ """ Test 16. Set distance from the Origin to the minor axis of the ellipse
+ """
+ self.checkPointLineDistance(self.myOrigin.coordinates(), self.myMinorAxis)
+
+
+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 constraint "Equal" applied to the pair of ellipses
+"""
+
+from salome.shaper import model
+import math
+
+DOF = 0
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchEllipse_1 = Sketch_1.addEllipse(-27.88698315421018, 6.197107367602265, -8.725072906579975, 15.87998754592604, 11.10896680773502)
+[SketchPoint_1, SketchPoint_2, SketchPoint_3, SketchPoint_4, SketchPoint_5, SketchPoint_6, SketchPoint_7, SketchLine_1, SketchLine_2] = SketchEllipse_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+DOF += 5
+SketchEllipse_2 = Sketch_1.addEllipse(15.14848467636108, -15.95181340919842, 21.12194589112931, -20.27742325437541, 9.877448119278471)
+[SketchPoint_8, SketchPoint_9, SketchPoint_10, SketchPoint_11, SketchPoint_12, SketchPoint_13, SketchPoint_14, SketchLine_3, SketchLine_4] = SketchEllipse_2.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+DOF += 5
+SketchEllipticArc_1 = Sketch_1.addEllipticArc(49.62123971365138, 13.34935433264426, 64.40153327705804, 5.234651852264014, 68.29270956846837, 8.653290073592997, 32.00833375829566, 14.82599483073829, False)
+[SketchPoint_15, SketchPoint_16, SketchPoint_17, SketchPoint_18, SketchPoint_19, SketchPoint_20, SketchPoint_21, SketchLine_5, SketchLine_6] = SketchEllipticArc_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+DOF += 7
+SketchEllipticArc_2 = Sketch_1.addEllipticArc(7.849720447428027, 32.28934430567138, 19.71732573395684, 29.13862828729395, 12.53096585507117, 17.93622281956947, 4.288678376456463, 46.71874313598852, True)
+[SketchPoint_22, SketchPoint_23, SketchPoint_24, SketchPoint_25, SketchPoint_26, SketchPoint_27, SketchPoint_28, SketchLine_7, SketchLine_8] = SketchEllipticArc_2.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+DOF += 7
+SketchConstraintEqual_1 = Sketch_1.setEqual(SketchEllipse_1.result(), SketchEllipse_2.result())
+DOF -= 2
+SketchConstraintEqual_2 = Sketch_1.setEqual(SketchEllipse_1.result(), SketchEllipticArc_1.result())
+DOF -= 2
+SketchConstraintEqual_3 = Sketch_1.setEqual(SketchEllipticArc_1.result(), SketchEllipticArc_2.result())
+DOF -= 2
+model.do()
+model.end()
+
+TOLERANCE = 1.e-7
+
+dist1 = model.distancePointPoint(SketchEllipse_1.majorAxisNegative(), SketchEllipse_1.majorAxisPositive())
+dist2 = model.distancePointPoint(SketchEllipse_2.majorAxisNegative(), SketchEllipse_2.majorAxisPositive())
+dist3 = model.distancePointPoint(SketchEllipticArc_1.majorAxisNegative(), SketchEllipticArc_1.majorAxisPositive())
+dist4 = model.distancePointPoint(SketchEllipticArc_2.majorAxisNegative(), SketchEllipticArc_2.majorAxisPositive())
+assert(math.fabs(dist1 - dist2) < TOLERANCE)
+assert(math.fabs(dist1 - dist3) < TOLERANCE)
+assert(math.fabs(dist1 - dist4) < TOLERANCE)
+
+dist1 = model.distancePointPoint(SketchEllipse_1.minorAxisNegative(), SketchEllipse_1.minorAxisPositive())
+dist2 = model.distancePointPoint(SketchEllipse_2.minorAxisNegative(), SketchEllipse_2.minorAxisPositive())
+dist3 = model.distancePointPoint(SketchEllipticArc_1.minorAxisNegative(), SketchEllipticArc_1.minorAxisPositive())
+dist4 = model.distancePointPoint(SketchEllipticArc_2.minorAxisNegative(), SketchEllipticArc_2.minorAxisPositive())
+assert(math.fabs(dist1 - dist2) < TOLERANCE)
+assert(math.fabs(dist1 - dist3) < TOLERANCE)
+assert(math.fabs(dist1 - dist4) < TOLERANCE)
+
+assert(model.dof(Sketch_1) == DOF)
+
+assert(model.checkPythonDump())
--- /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 middle point on an arc
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+from GeomAPI import GeomAPI_Dir2d
+
+__updated__ = "2019-09-03"
+
+class TestMiddlePointOnArc(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myTestPassed = True
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myArc = self.mySketch.addArc(50, 50, 70, 50, 50, 70, False)
+ self.myLine = self.mySketch.addLine(55, 60, 50, 0)
+ self.myDOF = 9
+ model.do()
+ self.checkDOF()
+
+ def tearDown(self):
+ if self.myTestPassed:
+ model.assertArcValidity(self.myArc)
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.checkDOF()
+ model.end()
+ assert(model.checkPythonDump())
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkMiddlePoint(self, thePoint, theArc):
+ self.myTestPassed = False
+ # check point on arc
+ dist = thePoint.pnt().distance(theArc.center().pnt())
+ NB_DIGITS = 7 - math.floor(math.log10(theArc.radius().value()))
+ self.assertAlmostEqual(dist, theArc.radius().value(), NB_DIGITS)
+ # check middle point
+ dirPC = GeomAPI_Dir2d(thePoint.x() - theArc.center().x(),
+ thePoint.y() - theArc.center().y())
+ dirSC = GeomAPI_Dir2d(theArc.startPoint().x() - theArc.center().x(),
+ theArc.startPoint().y() - theArc.center().y())
+ dirEC = GeomAPI_Dir2d(theArc.endPoint().x() - theArc.center().x(),
+ theArc.endPoint().y() - theArc.center().y())
+ angleSP = dirSC.angle(dirPC)
+ anglePE = dirPC.angle(dirEC)
+ self.assertAlmostEqual(angleSP, anglePE)
+ self.assertEqual(angleSP < 0, theArc.reversed().value())
+ self.myTestPassed = True
+
+ def rotatePoint(self, thePoint, theCenter, theAngle):
+ dirX = thePoint.x() - theCenter.x()
+ dirY = thePoint.y() - theCenter.y()
+ newX = theCenter.x() + dirX * math.cos(theAngle) - dirY * math.sin(theAngle)
+ newY = theCenter.y() + dirX * math.sin(theAngle) + dirY * math.cos(theAngle)
+ self.mySketch.move(thePoint, newX, newY)
+
+ def moveArc(self):
+ ANGLE_STEP = math.pi * 5.0 / 180.0
+ ANGLE_THRESHOLD = math.pi
+ # move start point of the arc clockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), -ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+ # move start point of the arc conterclockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+
+ # move end point of the arc clockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), -ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+ # move end point of the arc conterclockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+
+ # move center of the arc
+ DELTA = [1.0, 1.0]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ DELTA = [-1.0, 1.0]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+
+ def moveLine(self):
+ DELTA = [1.0, 0.0]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ DELTA = [0.0, 1.0]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+
+
+ def test_middle_point_PA(self):
+ """ Test 1. Set middle point constraint (point is the first argument)
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+
+ def test_middle_point_AP(self):
+ """ Test 2. Set middle point constraint (point is the second argument)
+ """
+ self.mySketch.setMiddlePoint(self.myArc.results()[1], self.myLine.startPoint())
+ self.myDOF -= 2
+ model.do()
+
+ def test_coincident_middle_point(self):
+ """ Test 3. Set middle point constraint for the point already coincident with the arc
+ """
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[1])
+ model.do()
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+
+ def test_middle_point_coincident(self):
+ """ Test 4. Set concidence of the point and the arc which are already constrained with middle point
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ model.do()
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+
+ @unittest.expectedFailure
+ def test_middle_point_limitation(self):
+ """ Test 5. Check middle point fails if the point's coordinates are equal to the arc boundary point
+ """
+ self.myLine.startPoint().setValue(self.myArc.endPoint().pnt())
+ model.do()
+ coincidence = self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[1])
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+ # this check will fail due to the limitation of PlanGCS
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+
+ def test_middle_point_move_arc(self):
+ """ Test 6. Set middle point constraint and move arc
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveArc()
+
+ def test_middle_point_coincidence_move_arc(self):
+ """ Test 7. Set coincidence and middle point constraint and move arc
+ """
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[1])
+ model.do()
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveArc()
+
+ def test_middle_point_move_line(self):
+ """ Test 8. Set middle point constraint and move line
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveLine()
+
+ def test_middle_point_coincidence_move_line(self):
+ """ Test 9. Set coincidence and middle point constraint and move line
+ """
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[1])
+ model.do()
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveLine()
+
+ def test_remove_middle_point(self):
+ """ Test 10. Set and then remove middle point constraint
+ """
+ mp = self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[1])
+ self.myDOF -= 2
+ model.do()
+ model.assertArcValidity(self.myArc)
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.checkDOF()
+ # remove middle point
+ self.myDocument.removeFeature(mp.feature())
+ self.myDOF += 2
+ model.do()
+ self.checkDOF()
+ # set flag False to avoid checking middle point constraint in tearDown() method
+ self.myTestPassed = False
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
--- /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 middle point on an elliptic arc
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-10-02"
+
+class TestMiddlePointOnEllipticArc(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myTestPassed = True
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myArc = self.mySketch.addEllipticArc(30, 20, 50, 30, 45, 40, 5, 6.11485435, False)
+ self.myLine = self.mySketch.addLine(10, 40, 40, 80)
+ self.myDOF = 11
+ model.do()
+ self.checkDOF()
+
+ def tearDown(self):
+ if self.myTestPassed:
+ self.assertArc(self.myArc)
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.checkDOF()
+ model.end()
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def toPeriod(self, theValue):
+ while theValue < -math.pi:
+ theValue += 2.0 * math.pi
+ while theValue >= math.pi:
+ theValue -= 2.0 * math.pi
+ return theValue
+
+ def checkMiddlePoint(self, thePoint, theArc):
+ self.myTestPassed = False
+ anEllipse = theArc.defaultResult().shape().edge().ellipse()
+ # check point on ellipse
+ self.checkPointOnEllipse(thePoint, anEllipse)
+ # check angles
+ TOLERANCE = 1.e-5
+ startAngle = 0; startPoint = GeomAPI_Pnt(theArc.startPoint().x(), theArc.startPoint().y(), 0)
+ startAngle = anEllipse.parameter(startPoint, TOLERANCE, startAngle)
+ endAngle = 0; endPoint = GeomAPI_Pnt(theArc.endPoint().x(), theArc.endPoint().y(), 0)
+ endAngle = anEllipse.parameter(endPoint, TOLERANCE, endAngle)
+ midAngle = 0; midPoint = GeomAPI_Pnt(thePoint.x(), thePoint.y(), 0)
+ midAngle = anEllipse.parameter(midPoint, TOLERANCE, midAngle)
+ diffMS = self.toPeriod(midAngle - startAngle)
+ diffEM = self.toPeriod(endAngle - midAngle)
+ self.assertAlmostEqual(diffMS, diffEM)
+ self.assertEqual(diffMS < 0, theArc.reversed().value())
+ self.myTestPassed = True
+
+ def checkPointOnEllipse(self, theCoordinates, theEllipse):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, point)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, point)
+ if issubclass(type(theEllipse), SketchAPI_Ellipse):
+ majorRad = theEllipse.majorRadius().value()
+ else:
+ majorRad = theEllipse.majorRadius()
+ NB_DIGITS = 7 - math.floor(math.log10(majorRad))
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * majorRad, NB_DIGITS)
+
+ def assertArc(self, theArc):
+ anEllipse = theArc.defaultResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(theArc.startPoint(), anEllipse)
+ self.checkPointOnEllipse(theArc.endPoint(), anEllipse)
+
+ def rotatePoint(self, thePoint, theCenter, theAngle):
+ dirX = thePoint.x() - theCenter.x()
+ dirY = thePoint.y() - theCenter.y()
+ newX = theCenter.x() + dirX * math.cos(theAngle) - dirY * math.sin(theAngle)
+ newY = theCenter.y() + dirX * math.sin(theAngle) + dirY * math.cos(theAngle)
+ self.mySketch.move(thePoint, newX, newY)
+
+ def moveArc(self):
+ ANGLE_STEP = math.pi * 5.0 / 180.0
+ ANGLE_THRESHOLD = math.pi / 2.0
+ # move start point of the arc clockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), -ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+ # move start point of the arc conterclockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.startPoint(), self.myArc.center(), ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+
+ # move end point of the arc clockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), -ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+ # move end point of the arc conterclockwise
+ fullAngle = 0.0
+ while fullAngle < ANGLE_THRESHOLD:
+ self.rotatePoint(self.myArc.endPoint(), self.myArc.center(), ANGLE_STEP)
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ fullAngle += ANGLE_STEP
+
+ # move center of the arc
+ DELTA = [0.1, 0.1]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ DELTA = [-0.1, 0.1]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myArc.center(), self.myArc.center().x() + DELTA[0], self.myArc.center().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+
+ def moveLine(self):
+ DELTA = [0.1, 0.0]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ DELTA = [0.0, 0.1]
+ for i in range(0, 40):
+ if i == 10 or i == 30:
+ DELTA = [-DELTA[0], -DELTA[1]]
+ self.mySketch.move(self.myLine.startPoint(), self.myLine.startPoint().x() + DELTA[0], self.myLine.startPoint().y() + DELTA[1])
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+
+
+ def test_middle_point_PA(self):
+ """ Test 1. Set middle point constraint (point is the first argument)
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+
+ def test_middle_point_AP(self):
+ """ Test 2. Set middle point constraint (point is the second argument)
+ """
+ self.mySketch.setMiddlePoint(self.myArc.results()[-1], self.myLine.startPoint())
+ self.myDOF -= 2
+ model.do()
+
+ def test_coincident_middle_point(self):
+ """ Test 3. Set middle point constraint for the point already coincident with the arc
+ """
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
+ model.do()
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+
+ def test_middle_point_coincident(self):
+ """ Test 4. Set concidence of the point and the arc which are already constrained with middle point
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ model.do()
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+
+ @unittest.expectedFailure
+ def test_middle_point_limitation(self):
+ """ Test 5. Check middle point fails if the point's coordinates are equal to the arc start point
+ """
+ self.myLine.startPoint().setValue(self.myArc.startPoint().pnt())
+ model.do()
+ coincidence = self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+ # this check will fail due to the limitation of PlanGCS
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+
+ def test_middle_point_equal_start(self):
+ """ Test 6. Check middle point does not fail if the point's coordinates are equal to the arc end point
+ """
+ self.myLine.startPoint().setValue(self.myArc.endPoint().pnt())
+ model.do()
+ coincidence = self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+
+ def test_middle_point_move_arc(self):
+ """ Test 7. Set middle point constraint and move arc
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveArc()
+
+ def test_middle_point_coincidence_move_arc(self):
+ """ Test 8. Set coincidence and middle point constraint and move arc
+ """
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
+ model.do()
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveArc()
+
+ def test_middle_point_move_line(self):
+ """ Test 9. Set middle point constraint and move line
+ """
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveLine()
+
+ def test_middle_point_coincidence_move_line(self):
+ """ Test 10. Set coincidence and middle point constraint and move line
+ """
+ self.mySketch.setCoincident(self.myLine.startPoint(), self.myArc.results()[-1])
+ model.do()
+ self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.moveLine()
+
+ def test_remove_middle_point(self):
+ """ Test 11. Set and then remove middle point constraint
+ """
+ mp = self.mySketch.setMiddlePoint(self.myLine.startPoint(), self.myArc.results()[-1])
+ self.myDOF -= 2
+ model.do()
+ self.assertArc(self.myArc)
+ self.checkMiddlePoint(self.myLine.startPoint(), self.myArc)
+ self.checkDOF()
+ # remove middle point
+ self.myDocument.removeFeature(mp.feature())
+ self.myDOF += 2
+ model.do()
+ self.checkDOF()
+ # set flag False to avoid checking middle point constraint in tearDown() method
+ self.myTestPassed = False
+
+
+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
+#
+
+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"))
+SketchCircle_1 = Sketch_1.addCircle(-35, -10, 20)
+SketchLine_1 = Sketch_1.addLine(-21, 2, 24, 21)
+SketchLine_2 = Sketch_1.addLine(24, 21, 20, -30)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchArc_1 = Sketch_1.addArc(25, -30, 42, -34, 13, -17.31142245955048, False)
+model.do()
+
+# check error on perpendicularity of circle and arc
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchCircle_1.results()[1], SketchArc_1.results()[1])
+model.do()
+assert(SketchConstraintPerpendicular_1.feature().error() != "")
+
+# avoid the failure
+Part_1_doc.removeFeature(SketchConstraintPerpendicular_1.feature())
+model.do()
+assert(Sketch_1.feature().error() == "")
+
+# set correct constraints
+SketchConstraintPerpendicular_2 = Sketch_1.setPerpendicular(SketchCircle_1.results()[1], SketchLine_1.result())
+SketchConstraintPerpendicular_3 = Sketch_1.setPerpendicular(SketchLine_2.result(), SketchArc_1.results()[1])
+model.do()
+
+TOLERANCE = 1.e-7
+assert(model.distancePointLine(SketchCircle_1.center(), SketchLine_1) < TOLERANCE)
+assert(model.distancePointLine(SketchArc_1.center(), SketchLine_2) < TOLERANCE)
+model.end()
+
+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
+import math
+from GeomAPI import *
+
+TOLERANCE = 1.e-7
+
+def checkPerpendicular(theLine, theEllipse):
+ focus1 = theEllipse.firstFocus()
+ focus2 = theEllipse.secondFocus()
+ pf1 = theLine.project(focus1)
+ pf2 = theLine.project(focus2)
+ dist1 = focus1.distance(pf1)
+ dist2 = focus2.distance(pf2)
+ if math.fabs(dist1 - dist2) < TOLERANCE:
+ # no need further check, the line is equal to one of the ellipses axis
+ return
+ x = (dist2 * pf1.x() - dist1 * pf2.x()) / (dist2 - dist1)
+ y = (dist2 * pf1.y() - dist1 * pf2.y()) / (dist2 - dist1)
+ pnt = GeomAPI_Pnt(x, y, 0)
+ # check point on ellipse
+ majorRad = theEllipse.majorRadius()
+ assert(math.fabs(pnt.distance(focus1) + pnt.distance(focus2) - 2.0 * majorRad) < TOLERANCE * majorRad)
+
+
+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(-40, 10, -20, 30)
+SketchArc_1 = Sketch_1.addArc(25, -30, 42, -34, 13, -17.31142245955048, False)
+SketchEllipse_1 = Sketch_1.addEllipse(-50, 0, -30, -5, 15)
+[SketchPoint_1, SketchPoint_2, SketchPoint_3, SketchPoint_4, SketchPoint_5, SketchPoint_6, SketchPoint_7, SketchLine_2, SketchLine_3] = SketchEllipse_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+SketchEllipticArc_1 = Sketch_1.addEllipticArc(5, 30, -5, 45, -7, 47, 15, 33.68010611, False)
+[SketchPoint_8, SketchPoint_9, SketchPoint_10, SketchPoint_11, SketchPoint_12, SketchPoint_13, SketchPoint_14, SketchLine_4, SketchLine_5] = SketchEllipticArc_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+model.do()
+
+# check error on perpendicularity of arc and elliptic arc
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchArc_1.results()[1], SketchEllipticArc_1.result())
+model.do()
+assert(SketchConstraintPerpendicular_1.feature().error() != "")
+
+# avoid the failure
+Part_1_doc.removeFeature(SketchConstraintPerpendicular_1.feature())
+model.do()
+assert(Sketch_1.feature().error() == "")
+
+# set correct constraints
+SketchConstraintPerpendicular_2 = Sketch_1.setPerpendicular(SketchEllipticArc_1.result(), SketchLine_1.result())
+SketchConstraintPerpendicular_3 = Sketch_1.setPerpendicular(SketchLine_1.result(), SketchEllipse_1.result())
+model.do()
+
+checkPerpendicular(SketchLine_1.defaultResult().shape().edge().line(), SketchEllipse_1.defaultResult().shape().edge().ellipse())
+checkPerpendicular(SketchLine_1.defaultResult().shape().edge().line(), SketchEllipticArc_1.defaultResult().shape().edge().ellipse())
+model.end()
+
+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 constraint "Tangent" applied to ellipse and another entity
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-20"
+
+class TestTangentEllipse(unittest.TestCase):
+ def setUp(self):
+ axisStart = GeomAPI_Pnt2d(20., 60.)
+ axisEnd = GeomAPI_Pnt2d(80., 50.)
+ passedPoint = GeomAPI_Pnt2d(60., 70.)
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipse = self.mySketch.addEllipse(axisStart, axisEnd, passedPoint, False)
+ model.do()
+ self.myEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ self.myCenter = macroEllipse.center()
+ self.myFocus1 = macroEllipse.focus1()
+ self.myFocus2 = macroEllipse.focus2()
+ self.myMajorAxis = macroEllipse.majorAxis()
+ self.myMajorStart = macroEllipse.majorAxisStart()
+ self.myMajorEnd = macroEllipse.majorAxisEnd()
+ self.myMinorAxis = macroEllipse.minorAxis()
+ self.myMinorStart = macroEllipse.minorAxisStart()
+ self.myMinorEnd = macroEllipse.minorAxisEnd()
+
+ self.myDOF = 5
+ self.myNbPoints = 7
+ self.myNbLines = 2
+ self.myNbArcs = 0
+ self.myNbCircles = 0
+ self.myNbEllipses = 1
+ self.myNbInternals = 11
+ self.myNbCoincidence = 0
+ self.myNbTangency = 0
+
+ def tearDown(self):
+ model.end()
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipse.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipse.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipse.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipse.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipse.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipse.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipse.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipse.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", self.myNbPoints)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", self.myNbLines)
+ model.testNbSubFeatures(self.mySketch, "SketchArc", self.myNbArcs)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", self.myNbCircles)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", self.myNbEllipses)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", self.myNbInternals)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", self.myNbCoincidence)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintTangent", self.myNbTangency)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def assertTangentLineEllipse(self, theLine, theEllipse):
+ aLine = GeomAPI_Lin2d(theLine.startPoint().pnt(), theLine.endPoint().pnt())
+ projF1 = aLine.project(theEllipse.firstFocus().pnt())
+ projF2 = aLine.project(theEllipse.secondFocus().pnt())
+
+ distF1P1 = model.distancePointPoint(theEllipse.firstFocus(), projF1)
+ distF2P2 = model.distancePointPoint(theEllipse.secondFocus(), projF2)
+
+ tgPoint = GeomAPI_Pnt2d((projF1.x() * distF2P2 + projF2.x() * distF1P1) / (distF1P1 + distF2P2), (projF1.y() * distF2P2 + projF2.y() * distF1P1) / (distF1P1 + distF2P2))
+ distF1T = model.distancePointPoint(theEllipse.firstFocus(), tgPoint)
+ distF2T = model.distancePointPoint(theEllipse.secondFocus(), tgPoint)
+ self.assertAlmostEqual(distF1T + distF2T, 2 * theEllipse.majorRadius().value())
+
+ def assertTangentCircleEllipse(self, theCircle, theEllipse):
+ axis = GeomAPI_Dir2d(theEllipse.firstFocus().x() - theEllipse.center().x(), theEllipse.firstFocus().y() - theEllipse.center().y())
+ anEllipse = GeomAPI_Ellipse2d(theEllipse.center().pnt(), axis, theEllipse.majorRadius().value(), theEllipse.minorRadius().value())
+ aCircle = GeomAPI_Circ2d(theCircle.center().pnt(), GeomAPI_Dir2d(1, 0), theCircle.radius().value())
+
+ pOnE = GeomAPI_Pnt2d(0, 0)
+ pOnC = GeomAPI_Pnt2d(0, 0)
+ anEllipse.distance(aCircle, pOnE, pOnC)
+ self.assertAlmostEqual(model.distancePointPoint(pOnE, theCircle.center()), theCircle.radius().value())
+
+ dist1 = model.distancePointPoint(pOnC, theEllipse.firstFocus())
+ dist2 = model.distancePointPoint(pOnC, theEllipse.secondFocus())
+ self.assertAlmostEqual(dist1 + dist2, 2 * theEllipse.majorRadius().value())
+
+ def assertTangentEllipses(self, theEllipse1, theEllipse2):
+ axis1 = GeomAPI_Dir2d(theEllipse1.firstFocus().x() - theEllipse1.center().x(), theEllipse1.firstFocus().y() - theEllipse1.center().y())
+ anEllipse1 = GeomAPI_Ellipse2d(theEllipse1.center().pnt(), axis1, theEllipse1.majorRadius().value(), theEllipse1.minorRadius().value())
+ axis2 = GeomAPI_Dir2d(theEllipse2.firstFocus().x() - theEllipse2.center().x(), theEllipse2.firstFocus().y() - theEllipse2.center().y())
+ anEllipse2 = GeomAPI_Ellipse2d(theEllipse2.center().pnt(), axis2, theEllipse2.majorRadius().value(), theEllipse2.minorRadius().value())
+
+ p1 = GeomAPI_Pnt2d(0, 0)
+ p2 = GeomAPI_Pnt2d(0, 0)
+ anEllipse1.distance(anEllipse2, p1, p2)
+
+ dist1 = model.distancePointPoint(p2, theEllipse1.firstFocus())
+ dist2 = model.distancePointPoint(p2, theEllipse1.secondFocus())
+ self.assertAlmostEqual(dist1 + dist2, 2 * theEllipse1.majorRadius().value())
+
+ dist1 = model.distancePointPoint(p1, theEllipse2.firstFocus())
+ dist2 = model.distancePointPoint(p1, theEllipse2.secondFocus())
+ self.assertAlmostEqual(dist1 + dist2, 2 * theEllipse2.majorRadius().value())
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x())
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y())
+
+
+ def test_line_tangent(self):
+ """ Test 1. Set tangency between ellipse and a line
+ """
+ aLine = self.mySketch.addLine(10, 10, 90, 40)
+ self.myNbLines += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipse)
+
+
+ def test_line_coincident_then_tangent(self):
+ """ Test 2. Set tangency between ellipse and a line, if the extremity of the line is coincident with the ellipse
+ """
+ aLine = self.mySketch.addLine(10, 10, 90, 40)
+ self.mySketch.setCoincident(aLine.endPoint(), self.myEllipse.result())
+ self.myNbLines += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipse)
+
+
+ def test_line_tangent_then_coincident(self):
+ """ Test 3. Set tangency between ellipse and a line, after that apply coincidence of extremity of the line and the ellipse's curve
+ """
+ aLine = self.mySketch.addLine(10, 10, 90, 40)
+ self.myNbLines += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.mySketch.setCoincident(aLine.startPoint(), self.myEllipse.result())
+ self.myNbCoincidence += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipse)
+
+
+ def test_line_tangent_then_remove_coincidence(self):
+ """ Test 4. Set tangency between ellipse and a line, which have a coincident point, then remove this coincidence
+ """
+ aLine = self.mySketch.addLine(10, 10, 90, 40)
+ aCoincidence = self.mySketch.setCoincident(aLine.endPoint(), self.myEllipse.result())
+ self.myNbLines += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.myDocument.removeFeature(aCoincidence.feature())
+ self.myNbCoincidence -= 1
+ self.myDOF += 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipse)
+
+
+ def test_circle_tangent(self):
+ """ Test 5. Set tangency between ellipse and a circle
+ """
+ aCircle = self.mySketch.addCircle(30, 10, 20)
+ self.myNbCircles += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), aCircle.defaultResult())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(aCircle, self.myEllipse)
+
+
+ def test_circle_coincident_then_tangent(self):
+ """ Test 6. Set tangency between ellipse and a circle, if the circle is coincident with start point of ellipse's minor axis
+ """
+ aCircle = self.mySketch.addCircle(30, 10, 20)
+ self.mySketch.setCoincident(self.myMinorStart.coordinates(), aCircle.defaultResult())
+ self.myNbCircles += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 2
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), aCircle.defaultResult())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(aCircle, self.myEllipse)
+ self.assertAlmostEqual(model.distancePointPoint(aCircle.center(), self.myMinorStart.coordinates()), aCircle.radius().value())
+
+
+ def test_arc_tangent(self):
+ """ Test 7. Set tangency between ellipse and a circular arc
+ """
+ anArc = self.mySketch.addArc(30, 10, 20, 10, 40, 10, False)
+ self.myNbArcs += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipse)
+
+
+ def test_arc_coincident_then_tangent(self):
+ """ Test 8. Set tangency between ellipse and an arc, if the extremity of the arc is coincident with the ellipse
+ """
+ anArc = self.mySketch.addArc(30, 10, 20, 10, 40, 10, False)
+ self.mySketch.setCoincident(anArc.endPoint(), self.myEllipse.result())
+ self.myNbArcs += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipse)
+
+
+ def test_arc_tangent_then_coincident(self):
+ """ Test 9. Set tangency between ellipse and an arc, after that apply coincidence of extremity of the arc and the ellipse's curve
+ """
+ anArc = self.mySketch.addArc(30, 10, 20, 10, 40, 10, False)
+ self.myNbArcs += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.mySketch.setCoincident(anArc.startPoint(), self.myEllipse.result())
+ self.myNbCoincidence += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipse)
+
+
+ def test_arc_tangent_then_remove_coincidence(self):
+ """ Test 10. Set tangency between ellipse and an arc, which have a coincident point, then remove this coincidence
+ """
+ anArc = self.mySketch.addArc(30, 10, 20, 10, 40, 10, False)
+ aCoincidence = self.mySketch.setCoincident(anArc.endPoint(), self.myEllipse.result())
+ self.myNbArcs += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.myDocument.removeFeature(aCoincidence.feature())
+ self.myNbCoincidence -= 1
+ self.myDOF += 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipse)
+
+
+ def test_ellipse_tangent(self):
+ """ Test 11. Set tangency between two ellipses
+ """
+ anEllipse = self.mySketch.addEllipse(10, 10, 20, -50, 20)
+ self.myNbEllipses += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipse.result(), anEllipse.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentEllipses(anEllipse, self.myEllipse)
+
+
+
+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 constraint "Tangent" applied to elliptic arc and another entity
+"""
+
+import unittest
+import math
+
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-10-04"
+
+class TestTangentEllipticArc(unittest.TestCase):
+ def setUp(self):
+ center = GeomAPI_Pnt2d(30., 20.)
+ axisEnd = GeomAPI_Pnt2d(50., 30.)
+ startPoint = GeomAPI_Pnt2d(45, 40)
+ endPoint = GeomAPI_Pnt2d(5, 6.11485435)
+
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ macroEllipticArc = self.mySketch.addEllipticArc(center, axisEnd, startPoint, endPoint, False)
+ model.do()
+ self.myEllipticArc = SketchAPI_EllipticArc(model.lastSubFeature(self.mySketch, "SketchEllipticArc"))
+ self.myCenter = macroEllipticArc.center()
+ self.myFocus1 = macroEllipticArc.focus1()
+ self.myFocus2 = macroEllipticArc.focus2()
+ self.myMajorAxis = macroEllipticArc.majorAxis()
+ self.myMajorStart = macroEllipticArc.majorAxisStart()
+ self.myMajorEnd = macroEllipticArc.majorAxisEnd()
+ self.myMinorAxis = macroEllipticArc.minorAxis()
+ self.myMinorStart = macroEllipticArc.minorAxisStart()
+ self.myMinorEnd = macroEllipticArc.minorAxisEnd()
+
+ self.myDOF = 7
+ self.myNbPoints = 7
+ self.myNbLines = 2
+ self.myNbArcs = 0
+ self.myNbCircles = 0
+ self.myNbEllipses = 0
+ self.myNbEllipticArcs = 1
+ self.myNbInternals = 11
+ self.myNbCoincidence = 0
+ self.myNbTangency = 0
+
+ def tearDown(self):
+ model.end()
+ self.checkDOF()
+ self.assertPoints(self.myCenter.coordinates(), self.myEllipticArc.center())
+ self.assertPoints(self.myFocus1.coordinates(), self.myEllipticArc.firstFocus())
+ self.assertPoints(self.myFocus2.coordinates(), self.myEllipticArc.secondFocus())
+ self.assertPoints(self.myMajorStart.coordinates(), self.myEllipticArc.majorAxisNegative())
+ self.assertPoints(self.myMajorEnd.coordinates(), self.myEllipticArc.majorAxisPositive())
+ self.assertPoints(self.myMajorAxis.startPoint(), self.myEllipticArc.majorAxisNegative())
+ self.assertPoints(self.myMajorAxis.endPoint(), self.myEllipticArc.majorAxisPositive())
+ self.assertPoints(self.myMinorStart.coordinates(), self.myEllipticArc.minorAxisNegative())
+ self.assertPoints(self.myMinorEnd.coordinates(), self.myEllipticArc.minorAxisPositive())
+ self.assertPoints(self.myMinorAxis.startPoint(), self.myEllipticArc.minorAxisNegative())
+ self.assertPoints(self.myMinorAxis.endPoint(), self.myEllipticArc.minorAxisPositive())
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", self.myNbPoints)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", self.myNbLines)
+ model.testNbSubFeatures(self.mySketch, "SketchArc", self.myNbArcs)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", self.myNbCircles)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", self.myNbEllipses)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", self.myNbEllipticArcs)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidenceInternal", self.myNbInternals)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", self.myNbCoincidence)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintTangent", self.myNbTangency)
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def assertTangentLineEllipse(self, theLine, theEllipticArc):
+ aLine = GeomAPI_Lin2d(theLine.startPoint().pnt(), theLine.endPoint().pnt())
+ projF1 = aLine.project(theEllipticArc.firstFocus().pnt())
+ projF2 = aLine.project(theEllipticArc.secondFocus().pnt())
+
+ distF1P1 = model.distancePointPoint(theEllipticArc.firstFocus(), projF1)
+ distF2P2 = model.distancePointPoint(theEllipticArc.secondFocus(), projF2)
+
+ tgPoint = GeomAPI_Pnt2d((projF1.x() * distF2P2 + projF2.x() * distF1P1) / (distF1P1 + distF2P2), (projF1.y() * distF2P2 + projF2.y() * distF1P1) / (distF1P1 + distF2P2))
+ distF1T = model.distancePointPoint(theEllipticArc.firstFocus(), tgPoint)
+ distF2T = model.distancePointPoint(theEllipticArc.secondFocus(), tgPoint)
+ NB_DIGITS = 7 - math.floor(math.log10(theEllipticArc.majorRadius().value()))
+ self.assertAlmostEqual(distF1T + distF2T, 2 * theEllipticArc.majorRadius().value(), NB_DIGITS)
+
+ def assertTangentCircleEllipse(self, theCircle, theEllipticArc):
+ axis = GeomAPI_Dir2d(theEllipticArc.firstFocus().x() - theEllipticArc.center().x(), theEllipticArc.firstFocus().y() - theEllipticArc.center().y())
+ anEllipticArc = GeomAPI_Ellipse2d(theEllipticArc.center().pnt(), axis, theEllipticArc.majorRadius().value(), theEllipticArc.minorRadius().value())
+ aCircle = GeomAPI_Circ2d(theCircle.center().pnt(), GeomAPI_Dir2d(1, 0), theCircle.radius().value())
+
+ pOnE = GeomAPI_Pnt2d(0, 0)
+ pOnC = GeomAPI_Pnt2d(0, 0)
+ anEllipticArc.distance(aCircle, pOnE, pOnC)
+ self.assertAlmostEqual(model.distancePointPoint(pOnE, theCircle.center()), theCircle.radius().value())
+
+ dist1 = model.distancePointPoint(pOnC, theEllipticArc.firstFocus())
+ dist2 = model.distancePointPoint(pOnC, theEllipticArc.secondFocus())
+ NB_DIGITS = 7 - math.floor(math.log10(theEllipticArc.majorRadius().value()))
+ self.assertAlmostEqual(dist1 + dist2, 2 * theEllipticArc.majorRadius().value(), NB_DIGITS)
+
+ def assertTangentEllipses(self, theEllipticArc1, theEllipticArc2):
+ axis1 = GeomAPI_Dir2d(theEllipticArc1.firstFocus().x() - theEllipticArc1.center().x(), theEllipticArc1.firstFocus().y() - theEllipticArc1.center().y())
+ anEllipticArc1 = GeomAPI_Ellipse2d(theEllipticArc1.center().pnt(), axis1, theEllipticArc1.majorRadius().value(), theEllipticArc1.minorRadius().value())
+ axis2 = GeomAPI_Dir2d(theEllipticArc2.firstFocus().x() - theEllipticArc2.center().x(), theEllipticArc2.firstFocus().y() - theEllipticArc2.center().y())
+ anEllipticArc2 = GeomAPI_Ellipse2d(theEllipticArc2.center().pnt(), axis2, theEllipticArc2.majorRadius().value(), theEllipticArc2.minorRadius().value())
+
+ p1 = GeomAPI_Pnt2d(0, 0)
+ p2 = GeomAPI_Pnt2d(0, 0)
+ anEllipticArc1.distance(anEllipticArc2, p1, p2)
+
+ dist1 = model.distancePointPoint(p2, theEllipticArc1.firstFocus())
+ dist2 = model.distancePointPoint(p2, theEllipticArc1.secondFocus())
+ NB_DIGITS = 7 - math.floor(math.log10(theEllipticArc1.majorRadius().value()))
+ self.assertAlmostEqual(dist1 + dist2, 2 * theEllipticArc1.majorRadius().value())
+
+ dist1 = model.distancePointPoint(p1, theEllipticArc2.firstFocus())
+ dist2 = model.distancePointPoint(p1, theEllipticArc2.secondFocus())
+ NB_DIGITS = 7 - math.floor(math.log10(theEllipticArc2.majorRadius().value()))
+ self.assertAlmostEqual(dist1 + dist2, 2 * theEllipticArc2.majorRadius().value(), NB_DIGITS)
+
+ def assertPoints(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 6)
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 6)
+
+
+ def test_line_tangent(self):
+ """ Test 1. Set tangency between elliptic arc and a line
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ self.myNbLines += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_line_coincident_then_tangent(self):
+ """ Test 2. Set tangency between elliptic arc and a line, if the extremity of the line is coincident with the elliptic arc
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ self.mySketch.setCoincident(aLine.endPoint(), self.myEllipticArc.result())
+ self.myNbLines += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_line_tangent_then_coincident(self):
+ """ Test 3. Set tangency between elliptic arc and a line, after that apply coincidence of extremity of the line and the elliptic arc's curve
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ self.myNbLines += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.mySketch.setCoincident(aLine.startPoint(), self.myEllipticArc.result())
+ self.myNbCoincidence += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_line_tangent_then_remove_coincidence(self):
+ """ Test 4. Set tangency between elliptic arc and a line, which have a coincident point, then remove this coincidence
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ aCoincidence = self.mySketch.setCoincident(aLine.endPoint(), self.myEllipticArc.result())
+ self.myNbLines += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.myDocument.removeFeature(aCoincidence.feature())
+ self.myNbCoincidence -= 1
+ self.myDOF += 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_line_coincident_point_then_tangent(self):
+ """ Test 5. Set tangency between elliptic arc and a line, if the extremity of the line is coincident with the start point of elliptic arc
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ self.mySketch.setCoincident(aLine.endPoint(), self.myEllipticArc.startPoint())
+ self.myNbLines += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 2
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_line_tangent_then_coincident_point(self):
+ """ Test 6. Set tangency between elliptic arc and a line, after that apply coincidence of extremities of the line and the elliptic arc
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ self.myNbLines += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+ self.mySketch.setCoincident(aLine.startPoint(), self.myEllipticArc.startPoint())
+ self.myNbCoincidence += 1
+ self.myDOF -= 2
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_line_tangent_then_remove_coincidence_on_extremity(self):
+ """ Test 7. Set tangency between elliptic arc and a line, which have a coincident boundary point, then remove this coincidence
+ """
+ aLine = self.mySketch.addLine(10, -10, 90, 40)
+ aCoincidence = self.mySketch.setCoincident(aLine.endPoint(), self.myEllipticArc.endPoint())
+ self.myNbLines += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 2
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aLine.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.myDocument.removeFeature(aCoincidence.feature())
+ self.myNbCoincidence -= 1
+ self.myDOF += 2
+ model.do()
+
+ self.assertTangentLineEllipse(aLine, self.myEllipticArc)
+
+
+ def test_circle_tangent(self):
+ """ Test 8. Set tangency between elliptic arc and a circle
+ """
+ aCircle = self.mySketch.addCircle(30, 10, 20)
+ self.myNbCircles += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aCircle.defaultResult())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(aCircle, self.myEllipticArc)
+
+
+ def test_circle_coincident_then_tangent(self):
+ """ Test 9. Set tangency between elliptic arc and a circle, if the circle is coincident with start point of elliptic arc's minor axis
+ """
+ aCircle = self.mySketch.addCircle(30, 10, 20)
+ self.mySketch.setCoincident(self.myEllipticArc.startPoint(), aCircle.defaultResult())
+ self.myNbCircles += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 2
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), aCircle.defaultResult())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(aCircle, self.myEllipticArc)
+ self.assertAlmostEqual(model.distancePointPoint(aCircle.center(), self.myEllipticArc.startPoint()), aCircle.radius().value())
+
+
+ def test_arc_tangent(self):
+ """ Test 10. Set tangency between elliptic arc and a circular arc
+ """
+ anArc = self.mySketch.addArc(30, -10, 40, -10, 20, -10, False)
+ self.myNbArcs += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipticArc)
+
+
+ def test_arc_coincident_then_tangent(self):
+ """ Test 11. Set tangency between elliptic arc and an arc, if the extremities of the arcs are coincident
+ """
+ anArc = self.mySketch.addArc(30, -10, 40, -10, 20, -10, False)
+ self.mySketch.setCoincident(anArc.endPoint(), self.myEllipticArc.startPoint())
+ self.myNbArcs += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipticArc)
+
+
+ def test_arc_tangent_then_coincident(self):
+ """ Test 12. Set tangency between elliptic arc and an arc, after that apply coincidence of extremities of the arcs
+ """
+ anArc = self.mySketch.addArc(30, -10, 40, -10, 20, -10, False)
+ self.myNbArcs += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.mySketch.setCoincident(anArc.startPoint(), self.myEllipticArc.startPoint())
+ self.myNbCoincidence += 1
+ self.myDOF -= 2
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipticArc)
+
+
+ def test_arc_tangent_then_remove_coincidence(self):
+ """ Test 13. Set tangency between elliptic arc and an arc, which have a coincident point, then remove this coincidence
+ """
+ anArc = self.mySketch.addArc(30, -10, 40, -10, 20, -10, False)
+ aCoincidence = self.mySketch.setCoincident(anArc.endPoint(), self.myEllipticArc.endPoint())
+ self.myNbArcs += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anArc.results()[-1])
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.myDocument.removeFeature(aCoincidence.feature())
+ self.myNbCoincidence -= 1
+ self.myDOF += 1
+ model.do()
+
+ self.assertTangentCircleEllipse(anArc, self.myEllipticArc)
+
+
+ def test_ellipse_tangent(self):
+ """ Test 14. Set tangency between ellipse and elliptic arc
+ """
+ anEllipse = self.mySketch.addEllipse(-30, 10, -10, 0, 20)
+ self.myNbEllipses += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anEllipse.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentEllipses(anEllipse, self.myEllipticArc)
+
+
+ def test_elliptic_arcs_tangent(self):
+ """ Test 15. Set tangency between two elliptic arcs
+ """
+ anEllipticArc = self.mySketch.addEllipticArc(35, 20, 60, 30, 40, 40, 20, -0.4890968089561491, True)
+ self.myNbEllipticArcs += 1
+ self.myDOF += 7
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anEllipticArc.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentEllipses(anEllipticArc, self.myEllipticArc)
+
+
+ def test_elliptic_arcs_coincident_then_tangent(self):
+ """ Test 16. Set tangency between two elliptic arcs, if their extremities are coincident
+ """
+ anEllipticArc = self.mySketch.addEllipticArc(35, 20, 60, 30, 40, 40, 20, -0.4890968089561491, True)
+ self.mySketch.setCoincident(anEllipticArc.startPoint(), self.myEllipticArc.endPoint())
+ self.myNbEllipticArcs += 1
+ self.myNbCoincidence += 1
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.setTangent(self.myEllipticArc.result(), anEllipticArc.result())
+ self.myNbTangency += 1
+ self.myDOF -= 1
+ model.do()
+
+ self.assertTangentEllipses(anEllipticArc, self.myEllipticArc)
+
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
--- /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
+#
+
+
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from GeomDataAPI import *
+from ModelAPI import *
+from SketchAPI import SketchAPI_Sketch
+import math
+from salome.shaper import model
+
+__updated__ = "2019-08-16"
+
+TOLERANCE = 1.e-7
+
+#=========================================================================
+# Auxiliary functions
+#=========================================================================
+
+def verifyLastArc(theSketch, theCenter, theStart, theEnd):
+ """
+ subroutine to verify position of last arc in the sketch
+ """
+ aLastArc = model.lastSubFeature(theSketch, "SketchArc")
+ model.assertArc(aLastArc, theCenter, theStart, theEnd)
+
+def verifyArcLineTransversal(theArc, theLine):
+ aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
+ aDistCL = model.distancePointLine(aCenter, theLine)
+ assert aDistCL < TOLERANCE, "Arc and line are not orthogonal"
+
+def verifyPointOnArc(thePoint, theArc):
+ aCenter = geomDataAPI_Point2D(theArc.attribute("center_point"))
+ aStart = geomDataAPI_Point2D(theArc.attribute("start_point"))
+ aRadius = model.distancePointPoint(aStart, aCenter)
+
+ aDistPP = model.distancePointPoint(aCenter, thePoint)
+ assert math.fabs(aRadius - aDistPP) < TOLERANCE, "Point is not on Circle, distance: {0}".format(aDistPP)
+
+
+
+aSession = ModelAPI_Session.get()
+aDocument = aSession.moduleDocument()
+#=========================================================================
+# Creation of a sketch
+#=========================================================================
+aSession.startOperation()
+aSketchCommonFeature = aDocument.addFeature("Sketch")
+aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
+origin.setValue(0, 0, 0)
+dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
+dirx.setValue(1, 0, 0)
+norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
+norm.setValue(0, 0, 1)
+aSession.finishOperation()
+aSketch = SketchAPI_Sketch(aSketchFeature)
+
+# auxiliary line
+aLineStartPnt = [0., 0.]
+aLineEndPnt = [50., 0.]
+aSession.startOperation()
+aSketchLine = aSketchFeature.addFeature("SketchLine")
+aLineStart = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
+aLineEnd = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint"))
+aLineStart.setValue(aLineStartPnt[0], aLineStartPnt[1])
+aLineEnd.setValue(aLineEndPnt[0], aLineEndPnt[1])
+aSession.finishOperation()
+
+#=========================================================================
+# Test 1. Create an arc, orthogonal to the line
+#=========================================================================
+anArcEndPnt = [80., 20.]
+aSession.startOperation()
+anArc = aSketchFeature.addFeature("SketchMacroArc")
+assert (anArc.getKind() == "SketchMacroArc")
+anArcTgPnt = anArc.refattr("tangent_point")
+assert (not anArcTgPnt.isInitialized())
+anArcEnd = geomDataAPI_Point2D(anArc.attribute("end_point_3"))
+assert (not anArcEnd.isInitialized())
+anArcType = anArc.string("arc_type")
+assert (not anArcType.isInitialized())
+# initialize attributes
+anArcType.setValue("by_transversal_line")
+anArcTgPnt.setAttr(aLineEnd)
+anArcEnd.setValue(anArcEndPnt[0], anArcEndPnt[1])
+aSession.finishOperation()
+verifyLastArc(aSketchFeature, [], aLineEndPnt, anArcEndPnt)
+aLastArc = model.lastSubFeature(aSketchFeature, "SketchArc")
+verifyArcLineTransversal(aLastArc, aSketchLine)
+model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 1)
+model.testNbSubFeatures(aSketch, "SketchConstraintPerpendicular", 1)
+
+#=========================================================================
+# Test 2. Create an arc, orthogonal to the previous arc (expect an error)
+#=========================================================================
+aPrevArc = aLastArc
+aPrevArcEnd = geomDataAPI_Point2D(aPrevArc.attribute("end_point"))
+anArcEndPnt = [50., 100.]
+aSession.startOperation()
+anArc = aSketchFeature.addFeature("SketchMacroArc")
+anArcTgPnt = anArc.refattr("tangent_point")
+anArcEnd = geomDataAPI_Point2D(anArc.attribute("end_point_3"))
+anArcType = anArc.string("arc_type")
+# initialize attributes
+anArcType.setValue("by_transversal_line")
+anArcTgPnt.setAttr(aPrevArcEnd)
+anArcEnd.setValue(anArcEndPnt[0], anArcEndPnt[1])
+aSession.finishOperation()
+assert(anArc.error() != "")
+# remove failed feature
+aSession.startOperation()
+aDocument.removeFeature(anArc)
+aSession.finishOperation()
+
+#=========================================================================
+# Test 3. Create an arc, orthogonal to the line with end point on the arc
+#=========================================================================
+aPrevArc = model.lastSubFeature(aSketchFeature, "SketchArc")
+aPrevArcEnd = geomDataAPI_Point2D(aPrevArc.attribute("end_point"))
+aSession.startOperation()
+anArc = aSketchFeature.addFeature("SketchMacroArc")
+anArcTgPnt = anArc.refattr("tangent_point")
+anArcEnd = geomDataAPI_Point2D(anArc.attribute("end_point_3"))
+anArcEndRef = anArc.refattr("end_point_ref")
+anArcType = anArc.string("arc_type")
+# initialize attributes
+anArcType.setValue("by_transversal_line")
+anArcTgPnt.setAttr(aLineStart)
+anArcEndRef.setObject(aPrevArc.lastResult())
+anArcEnd.setValue(anArcEndPnt[0], anArcEndPnt[1])
+aSession.finishOperation()
+verifyLastArc(aSketchFeature, [], [aLineStart.x(), aLineStart.y()], [])
+aLastArc = model.lastSubFeature(aSketchFeature, "SketchArc")
+verifyArcLineTransversal(aLastArc, aSketchLine)
+aLastArcEnd = geomDataAPI_Point2D(aLastArc.attribute("end_point"))
+verifyPointOnArc(aLastArcEnd, aPrevArc)
+model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3)
+model.testNbSubFeatures(aSketch, "SketchConstraintPerpendicular", 2)
+
+#=========================================================================
+# End of test
+#=========================================================================
+
+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 creation of ellipse by center, semi-axis and passed point
+"""
+
+import unittest
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-09"
+
+class TestEllipse(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myCenter = GeomAPI_Pnt2d(50., 50.)
+ self.myFocus = GeomAPI_Pnt2d(70., 50.)
+ self.myPassedPoint = GeomAPI_Pnt2d(60., 60.)
+ self.myMinorRadius = 20.
+ self.myDOF = 0
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointsEqual(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5)
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5)
+
+ def checkPointOnLine(self, theCoordinates, theLine):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ dist = model.distancePointLine(point, theLine)
+ self.assertAlmostEqual(dist, 0, 7)
+
+ def checkPointOnCircle(self, theCoordinates, theCircle):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ dist = model.distancePointPoint(point, theCircle.center())
+ self.assertAlmostEqual(dist , theCircle.radius().value(), 7)
+
+ def checkPointOnEllipse(self, theCoordinates, theEllipse):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, point)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, point)
+ if issubclass(type(theEllipse), SketchAPI_Ellipse):
+ majorRad = theEllipse.majorRadius().value()
+ else:
+ majorRad = theEllipse.majorRadius()
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * majorRad, 7)
+
+
+ def test_ellipse_by_center_and_focus(self):
+ """ Test 1. Create ellipse by coordinates of center, focus and minor radius
+ """
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter.x(), self.myCenter.y(), self.myFocus.x(), self.myFocus.y(), self.myMinorRadius)
+ self.myDOF += 5
+
+ self.myEllipse2 = self.mySketch.addEllipse(self.myCenter, self.myFocus, self.myMinorRadius)
+ self.myDOF += 5
+ model.do()
+
+ # check both ellipses are equal
+ anEllipse1 = self.myEllipse1.defaultResult().shape().edge().ellipse()
+ anEllipse2 = self.myEllipse2.defaultResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse1.center(), anEllipse2.center())
+ self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus())
+ self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus())
+ self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius())
+ self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 0)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 0)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+
+ def test_ellipse_by_semiaxis_and_passed(self):
+ """ Test 2. Create ellipse by coordinates of center, major semi-axis point and a passed point on ellipse
+ """
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter.x(), self.myCenter.y(), self.myFocus.x(), self.myFocus.y(), self.myPassedPoint.x(), self.myPassedPoint.y(), True)
+ self.myDOF += 5
+ model.do()
+ anEllipseFeature1 = model.lastSubFeature(self.mySketch, "SketchEllipse")
+
+ self.myEllipse2 = self.mySketch.addEllipse(self.myCenter, self.myFocus, self.myPassedPoint, True)
+ self.myDOF += 5
+ model.do()
+ anEllipseFeature2 = model.lastSubFeature(self.mySketch, "SketchEllipse")
+
+ # check both ellipses are equal
+ anEllipse1 = anEllipseFeature1.lastResult().shape().edge().ellipse()
+ anEllipse2 = anEllipseFeature2.lastResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse1.center(), anEllipse2.center())
+ self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus())
+ self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus())
+ self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius())
+ self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius())
+ # check passed point on ellipse
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse1)
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse2)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 14)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 4)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+
+ def test_ellipse_with_fixed_center(self):
+ """ Test 3. Create ellipse which center is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(aLine.endPoint(), self.myFocus, self.myPassedPoint, True)
+ self.myDOF += 3
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse.center(), aLine.endPoint())
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_center_on_line(self):
+ """ Test 4. Create ellipse which center is coincident with a line
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse([self.myCenter, aLine.result()], self.myFocus, self.myPassedPoint, True)
+ self.myDOF += 4
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ # check center on line
+ self.checkPointOnLine(anEllipse.center(), aLine)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_center_on_circle(self):
+ """ Test 5. Create ellipse which center is coincident with a circle
+ """
+ aCircle = self.mySketch.addCircle(10, 10, 20)
+ self.myDOF += 3
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse([self.myCenter, aCircle.defaultResult()], self.myFocus, self.myPassedPoint, True)
+ self.myDOF += 4
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ # check center on circle
+ self.checkPointOnCircle(anEllipse.center(), aCircle)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_center_on_ellipse(self):
+ """ Test 6. Create ellipse which center is coincident with another ellipse
+ """
+ anOtherEllipse = self.mySketch.addEllipse(10, 10, 30, 20, 10)
+ self.myDOF += 5
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse([self.myCenter, anOtherEllipse.defaultResult()], self.myFocus, self.myPassedPoint, True)
+ self.myDOF += 4
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ # check center on ellipse
+ self.checkPointOnEllipse(anEllipse.center(), anOtherEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_fixed_axis(self):
+ """ Test 7. Create ellipse which point on major semi-axis is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, aLine.endPoint(), self.myPassedPoint, True)
+ self.myDOF += 3
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse)
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ # check distance is equal to major semi-axis
+ dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.endPoint())
+ self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_on_line(self):
+ """ Test 8. Create ellipse which point on major semi-axis is coincident with a line
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, [self.myFocus, aLine.result()], self.myPassedPoint, True)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check axis point on line
+ self.checkPointOnLine(anEllipse.majorAxisPositive(), aLine)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_on_circle(self):
+ """ Test 9. Create ellipse which point on major semi-axis is coincident with a circle
+ """
+ aCircle = self.mySketch.addCircle(10, 10, 20)
+ self.myDOF += 3
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, [self.myFocus, aCircle.defaultResult()], self.myPassedPoint, True)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check center on circle
+ self.checkPointOnCircle(anEllipse.majorAxisPositive(), aCircle)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_on_ellipse(self):
+ """ Test 10. Create ellipse which point on major semi-axis is coincident with another ellipse
+ """
+ anOtherEllipse = self.mySketch.addEllipse(10, 10, 90, 40, 30)
+ self.myDOF += 5
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, [self.myFocus, anOtherEllipse.defaultResult()], self.myPassedPoint, True)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check center on ellipse
+ self.checkPointOnEllipse(anEllipse.majorAxisPositive(), anOtherEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_fixed_passed_point(self):
+ """ Test 11. Create ellipse which passed point is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, self.myFocus, aLine.endPoint(), True)
+ self.myDOF += 4
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_passed_point_on_line(self):
+ """ Test 12. Create ellipse which passed point is placed on a line.
+ Check no constraints is applied.
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, self.myFocus, [self.myPassedPoint, aLine.result()], True)
+ self.myDOF += 5
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ # check neither coincidence nor tangent feature exists
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 0)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintTangent", 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 creation of ellipse by external feature
+"""
+
+import unittest
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+# reference data
+CENTER_POINT = GeomAPI_Pnt2d(50., 50.)
+FOCUS_POINT = GeomAPI_Pnt2d(70., 60.)
+MINOR_RADIUS = 10.
+
+class TestEllipse(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myDOF = 0
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointsEqual(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5)
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5)
+
+
+ def test_ellipse_by_external_name(self):
+ """ Test 1. Create ellipse by name of external edge
+ """
+ self.myEllipse = self.mySketch.addEllipse("Sketch_1/SketchEllipse_1")
+ model.do()
+
+ # check ellipse parameters
+ anEllipse = self.myEllipse.defaultResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse.center(), CENTER_POINT)
+ self.checkPointsEqual(anEllipse.firstFocus(), FOCUS_POINT)
+ self.assertAlmostEqual(anEllipse.minorRadius(), MINOR_RADIUS)
+
+ def test_ellipse_by_external_selection(self):
+ """ Test 2. Create ellipse by selected edge
+ """
+ self.myEllipse = self.mySketch.addEllipse(ELLIPSE.results()[-1])
+ model.do()
+
+ # check ellipse parameters
+ anEllipse = self.myEllipse.defaultResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse.center(), CENTER_POINT)
+ self.checkPointsEqual(anEllipse.firstFocus(), FOCUS_POINT)
+ self.assertAlmostEqual(anEllipse.minorRadius(), MINOR_RADIUS)
+
+
+if __name__ == "__main__":
+ model.begin()
+ aDocument = model.moduleDocument()
+ aSketch = model.addSketch(aDocument, model.defaultPlane("XOY"))
+ ELLIPSE = aSketch.addEllipse(CENTER_POINT, FOCUS_POINT, MINOR_RADIUS)
+ model.end()
+
+ 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 creation of ellipse by majoraxis and passed point
+"""
+
+import unittest
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-09-12"
+
+class TestEllipse(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myAxisStart = GeomAPI_Pnt2d(30., 60.)
+ self.myAxisEnd = GeomAPI_Pnt2d(80., 50.)
+ self.myPassedPoint = GeomAPI_Pnt2d(60., 60.)
+ self.myDOF = 0
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointsEqual(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5)
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5)
+
+ def checkPointOnLine(self, theCoordinates, theLine):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ dist = model.distancePointLine(point, theLine)
+ self.assertAlmostEqual(dist, 0, 7)
+
+ def checkPointOnCircle(self, theCoordinates, theCircle):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ dist = model.distancePointPoint(point, theCircle.center())
+ self.assertAlmostEqual(dist , theCircle.radius().value(), 7)
+
+ def checkPointOnEllipse(self, theCoordinates, theEllipse):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, point)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, point)
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius(), 7)
+
+
+ def test_ellipse_by_axis_and_passed(self):
+ """ Test 1. Create ellipse by points defining major semi-axis and a passed point on ellipse
+ """
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart.x(), self.myAxisStart.y(), self.myAxisEnd.x(), self.myAxisEnd.y(), self.myPassedPoint.x(), self.myPassedPoint.y(), False)
+ self.myDOF += 5
+ model.do()
+ anEllipseFeature1 = model.lastSubFeature(self.mySketch, "SketchEllipse")
+
+ self.myEllipse2 = self.mySketch.addEllipse(self.myAxisStart, self.myAxisEnd, self.myPassedPoint, False)
+ self.myDOF += 5
+ model.do()
+ anEllipseFeature2 = model.lastSubFeature(self.mySketch, "SketchEllipse")
+
+ # check both ellipses are equal
+ anEllipse1 = anEllipseFeature1.lastResult().shape().edge().ellipse()
+ anEllipse2 = anEllipseFeature2.lastResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse1.center(), anEllipse2.center())
+ self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus())
+ self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus())
+ self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius())
+ self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius())
+ # check passed point on ellipse
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse1)
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse2)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 14)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 4)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+
+ def test_ellipse_with_fixed_axis_start(self):
+ """ Test 2. Create ellipse which negative point on the major axis coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(aLine.startPoint(), self.myAxisEnd, self.myPassedPoint, False)
+ self.myDOF += 3
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse)
+ self.checkPointOnEllipse(aLine.startPoint(), anEllipse)
+ # check distance is equal to major semi-axis
+ dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.startPoint())
+ self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_start_on_line(self):
+ """ Test 3. Create ellipse which negative point on the major axis coincident with a line
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse([self.myAxisStart, aLine.result()], self.myAxisEnd, self.myPassedPoint, False)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check negative point of major axis on line
+ self.checkPointOnLine(anEllipse.majorAxisNegative(), aLine)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_start_on_circle(self):
+ """ Test 4. Create ellipse which negative point on the major axis coincident with a circle
+ """
+ aCircle = self.mySketch.addCircle(10, 10, 20)
+ self.myDOF += 3
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse([self.myAxisStart, aCircle.defaultResult()], self.myAxisEnd, self.myPassedPoint, False)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check center on circle
+ self.checkPointOnCircle(anEllipse.majorAxisNegative(), aCircle)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_start_on_ellipse(self):
+ """ Test 5. Create ellipse which negative point on the major axis coincident with another ellipse
+ """
+ anOtherEllipse = self.mySketch.addEllipse(10, 10, 30, 20, 10)
+ self.myDOF += 5
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse([self.myAxisStart, anOtherEllipse.defaultResult()], self.myAxisEnd, self.myPassedPoint, False)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check center on ellipse
+ self.checkPointOnEllipse(anEllipse.majorAxisNegative(), anOtherEllipse.defaultResult().shape().edge().ellipse())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_fixed_axis_end(self):
+ """ Test 6. Create ellipse which positive point on the major axis coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 90, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, aLine.endPoint(), self.myPassedPoint, False)
+ self.myDOF += 3
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse)
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ # check distance is equal to major semi-axis
+ dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.endPoint())
+ self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_end_on_line(self):
+ """ Test 7. Create ellipse which negative point on the major axis coincident with a line
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, [self.myAxisEnd, aLine.result()], self.myPassedPoint, False)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check axis point on line
+ self.checkPointOnLine(anEllipse.majorAxisPositive(), aLine)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_end_on_circle(self):
+ """ Test 8. Create ellipse which negative point on the major axis coincident with a circle
+ """
+ aCircle = self.mySketch.addCircle(10, 10, 20)
+ self.myDOF += 3
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, [self.myAxisEnd, aCircle.defaultResult()], self.myPassedPoint, False)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check center on circle
+ self.checkPointOnCircle(anEllipse.majorAxisPositive(), aCircle)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_axis_end_on_ellipse(self):
+ """ Test 9. Create ellipse which negative point on the major axis coincident with another ellipse
+ """
+ anOtherEllipse = self.mySketch.addEllipse(10, 10, 90, 40, 30)
+ self.myDOF += 5
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, [self.myAxisEnd, anOtherEllipse.defaultResult()], self.myPassedPoint, False)
+ self.myDOF += 4
+ model.do()
+
+ anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse"))
+ # check center on ellipse
+ self.checkPointOnEllipse(anEllipse.majorAxisPositive(), anOtherEllipse.defaultResult().shape().edge().ellipse())
+ # check coincidence feature exists
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_fixed_passed_point(self):
+ """ Test 10. Create ellipse which passed point is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, self.myAxisEnd, aLine.endPoint(), False)
+ self.myDOF += 4
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_ellipse_with_passed_point_on_line(self):
+ """ Test 11. Create ellipse which passed point is placed on a line.
+ Check no constraints is applied.
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, self.myAxisEnd, [self.myPassedPoint, aLine.result()], False)
+ self.myDOF += 5
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse")
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(self.myPassedPoint, anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ # check neither coincidence nor tangent feature exists
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 0)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintTangent", 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 creation of elliptic arc by center, semi-axis, start and end points
+"""
+
+import unittest
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-10-01"
+
+class TestEllipticArc(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myCenter = GeomAPI_Pnt2d(50., 50.)
+ self.myFocus = GeomAPI_Pnt2d(70., 60.)
+ self.myStartPoint = GeomAPI_Pnt2d(60., 65.)
+ self.myEndPoint = GeomAPI_Pnt2d(60., 42.535751)
+ self.myDOF = 0
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointsEqual(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5)
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5)
+
+ def checkPointOnLine(self, theCoordinates, theLine):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ dist = model.distancePointLine(point, theLine)
+ self.assertAlmostEqual(dist, 0, 7)
+
+ def checkPointOnCircle(self, theCoordinates, theCircle):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ dist = model.distancePointPoint(point, theCircle.center())
+ self.assertAlmostEqual(dist , theCircle.radius().value(), 7)
+
+ def checkPointOnEllipse(self, theCoordinates, theEllipse):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, point)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, point)
+ if issubclass(type(theEllipse), SketchAPI_Ellipse):
+ majorRad = theEllipse.majorRadius().value()
+ else:
+ majorRad = theEllipse.majorRadius()
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * majorRad, 7)
+
+
+ def test_elliptic_arc_by_coordinates(self):
+ """ Test 1. Create elliptic arc by coordinates of center, point on the major axis, start and end points
+ """
+ self.myEllipse1 = self.mySketch.addEllipticArc(self.myCenter.x(), self.myCenter.y(),
+ self.myFocus.x(), self.myFocus.y(),
+ self.myStartPoint.x(), self.myStartPoint.y(),
+ self.myEndPoint.x(), self.myEndPoint.y(), False)
+ self.myDOF += 7
+
+ self.myEllipse2 = self.mySketch.addEllipticArc(self.myCenter.x(), self.myCenter.y(),
+ self.myFocus.x(), self.myFocus.y(),
+ self.myStartPoint.x(), self.myStartPoint.y(),
+ self.myEndPoint.x(), self.myEndPoint.y(), True)
+ self.myDOF += 7
+ model.do()
+
+ # check both ellipses are equal
+ anArcEdge1 = self.myEllipse1.defaultResult().shape().edge()
+ anArcEdge2 = self.myEllipse2.defaultResult().shape().edge()
+ anEllipse1 = anArcEdge1.ellipse()
+ anEllipse2 = anArcEdge2.ellipse()
+ self.checkPointsEqual(anEllipse1.center(), anEllipse2.center())
+ self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus())
+ self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus())
+ self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius())
+ self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius())
+ self.checkPointsEqual(self.myEllipse1.startPoint(), self.myEllipse2.startPoint())
+ self.checkPointsEqual(self.myEllipse1.endPoint(), self.myEllipse2.endPoint())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 0)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 0)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 2)
+ # check middle points are different
+ assert(anArcEdge1.middlePoint().x() < self.myStartPoint.x())
+ assert(anArcEdge2.middlePoint().x() > self.myStartPoint.x())
+
+ def test_elliptic_arc_by_points(self):
+ """ Test 2. Create elliptic arc by points
+ """
+ self.mySketch.addEllipticArc(self.myCenter, self.myFocus, self.myStartPoint, self.myEndPoint, False)
+ self.myDOF += 7
+ model.do()
+ anEllipseFeature1 = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature1)
+
+ self.mySketch.addEllipticArc(self.myCenter, self.myFocus, self.myStartPoint, self.myEndPoint, True)
+ self.myDOF += 7
+ model.do()
+ anEllipseFeature2 = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse2 = SketchAPI_EllipticArc(anEllipseFeature2)
+
+ # check both ellipses are equal
+ anArcEdge1 = anEllipseFeature1.lastResult().shape().edge()
+ anArcEdge2 = anEllipseFeature2.lastResult().shape().edge()
+ anEllipse1 = anArcEdge1.ellipse()
+ anEllipse2 = anArcEdge2.ellipse()
+ self.checkPointsEqual(anEllipse1.center(), anEllipse2.center())
+ self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus())
+ self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus())
+ self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius())
+ self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius())
+ self.checkPointsEqual(self.myEllipse1.startPoint(), self.myEllipse2.startPoint())
+ self.checkPointsEqual(self.myEllipse1.endPoint(), self.myEllipse2.endPoint())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 14)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 4)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 2)
+ # check middle points are different
+ assert(anArcEdge1.middlePoint().x() < self.myStartPoint.x())
+ assert(anArcEdge2.middlePoint().x() > self.myStartPoint.x())
+
+ def test_elliptic_arc_with_fixed_center(self):
+ """ Test 3. Create elliptic arc which center is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(aLine.endPoint(), self.myFocus, self.myStartPoint, self.myEndPoint, True)
+ self.myDOF += 5
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointsEqual(anEllipse.center(), aLine.endPoint())
+ self.checkPointOnEllipse(self.myStartPoint, anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_center_on_line(self):
+ """ Test 4. Create elliptic arc which center is coincident with a line
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc([self.myCenter, aLine.result()], self.myFocus, self.myStartPoint, self.myEndPoint, False)
+ self.myDOF += 6
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ # check center on line
+ self.checkPointOnLine(anEllipse.center(), aLine)
+ self.checkPointOnEllipse(self.myEllipse1.startPoint(), anEllipse)
+ self.checkPointOnEllipse(self.myEllipse1.endPoint(), anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_center_on_circle(self):
+ """ Test 5. Create elliptic arc which center is coincident with a circle
+ """
+ aCircle = self.mySketch.addCircle(10, 10, 20)
+ self.myDOF += 3
+ model.do()
+
+ self.mySketch.addEllipticArc([self.myCenter, aCircle.defaultResult()], self.myFocus, self.myStartPoint, self.myEndPoint, False)
+ self.myDOF += 6
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ # check center on circle
+ self.checkPointOnCircle(anEllipse.center(), aCircle)
+ self.checkPointOnEllipse(self.myEllipse1.startPoint(), anEllipse)
+ self.checkPointOnEllipse(self.myEllipse1.endPoint(), anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchCircle", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_center_on_ellipse(self):
+ """ Test 6. Create elliptic arc which center is coincident with another ellipse
+ """
+ anOtherEllipse = self.mySketch.addEllipse(10, 10, 30, 20, 10)
+ self.myDOF += 5
+ model.do()
+
+ self.mySketch.addEllipticArc([self.myCenter, anOtherEllipse.defaultResult()], self.myFocus, self.myStartPoint, self.myEndPoint, False)
+ self.myDOF += 6
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ # check center on ellipse
+ self.checkPointOnEllipse(anEllipse.center(), anOtherEllipse)
+ self.checkPointOnEllipse(self.myEllipse1.startPoint(), anEllipse)
+ self.checkPointOnEllipse(self.myEllipse1.endPoint(), anEllipse)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 2)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_fixed_axis(self):
+ """ Test 7. Create elliptic arc which point on major semi-axis is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(self.myCenter, aLine.endPoint(), self.myStartPoint, self.myEndPoint, False)
+ self.myDOF += 6
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(self.myStartPoint, anEllipse)
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ # check distance is equal to major semi-axis
+ dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.endPoint())
+ self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7)
+ self.checkPointsEqual(self.myEllipse1.majorAxisPositive(), aLine.endPoint())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_axis_on_line(self):
+ """ Test 8. Create elliptic arc which point on major semi-axis is coincident with a line.
+ Check no coincidence constraint is created.
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(self.myCenter, [self.myFocus, aLine.result()], self.myStartPoint, self.myEndPoint, True)
+ self.myDOF += 7
+ model.do()
+
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 0)
+
+ def test_elliptic_arc_with_fixed_start_point(self):
+ """ Test 9. Create elliptic arc which start point is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(self.myCenter, self.myFocus, aLine.endPoint(), self.myEndPoint, True)
+ self.myDOF += 5
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ self.checkPointsEqual(aLine.endPoint(), self.myEllipse1.startPoint())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_start_point_on_line(self):
+ """ Test 10. Create elliptic arc which start point is placed on a line.
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(self.myCenter, self.myFocus, [self.myStartPoint, aLine.result()], self.myEndPoint, False)
+ self.myDOF += 6
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnLine(self.myEllipse1.startPoint(), aLine)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_fixed_end_point(self):
+ """ Test 11. Create elliptic arc which end point is coincident with another point
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(self.myCenter, self.myFocus, self.myStartPoint, aLine.endPoint(), True)
+ self.myDOF += 5
+ model.do()
+ # check ellipse
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnEllipse(aLine.endPoint(), anEllipse)
+ self.checkPointsEqual(aLine.endPoint(), self.myEllipse1.endPoint())
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+ def test_elliptic_arc_with_end_point_on_line(self):
+ """ Test 12. Create elliptic arc which end point is placed on a line.
+ """
+ aLine = self.mySketch.addLine(10, 10, 30, 40)
+ self.myDOF += 4
+ model.do()
+
+ self.mySketch.addEllipticArc(self.myCenter, self.myFocus, self.myStartPoint, [self.myEndPoint, aLine.result()], False)
+ self.myDOF += 6
+ model.do()
+
+ anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipticArc")
+ self.myEllipse1 = SketchAPI_EllipticArc(anEllipseFeature)
+ anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse()
+ self.checkPointOnLine(self.myEllipse1.endPoint(), aLine)
+ # check number of features
+ model.testNbSubFeatures(self.mySketch, "SketchPoint", 7)
+ model.testNbSubFeatures(self.mySketch, "SketchLine", 3)
+ model.testNbSubFeatures(self.mySketch, "SketchEllipticArc", 1)
+ model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1)
+
+
+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 creation of elliptic arc by external feature
+"""
+
+import unittest
+from salome.shaper import model
+
+from GeomAPI import *
+from SketchAPI import *
+
+__updated__ = "2019-10-02"
+
+# reference data
+CENTER_POINT = GeomAPI_Pnt2d(50., 50.)
+MAJOR_AXIS_POINT = GeomAPI_Pnt2d(70., 60.)
+START_POINT = GeomAPI_Pnt2d(60., 65.)
+END_POINT = GeomAPI_Pnt2d(60., 42.535751)
+ARC_LENGTH_1 = 0
+ARC_LENGTH_2 = 0
+
+class TestEllipticArcByExternal(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myDOF = 0
+
+ def tearDown(self):
+ self.checkDOF()
+ model.end()
+
+
+ def checkDOF(self):
+ self.assertEqual(model.dof(self.mySketch), self.myDOF)
+
+ def checkPointsEqual(self, thePoint1, thePoint2):
+ self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5)
+ self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5)
+
+
+ def test_elliptic_arc_by_external_name_1(self):
+ """ Test 1. Create elliptic arc by name of external edge (direct)
+ """
+ self.myEllipse = self.mySketch.addEllipticArc("Sketch_1/SketchEllipticArc_1")
+ model.do()
+
+ # check ellipse parameters
+ anArcEdge = self.myEllipse.defaultResult().shape().edge()
+ anEllipse = anArcEdge.ellipse()
+ self.checkPointsEqual(anEllipse.center(), CENTER_POINT)
+ self.checkPointsEqual(self.myEllipse.majorAxisPositive(), MAJOR_AXIS_POINT)
+ self.checkPointsEqual(self.myEllipse.startPoint(), START_POINT)
+ self.checkPointsEqual(self.myEllipse.endPoint(), END_POINT)
+ self.assertAlmostEqual(anArcEdge.length(), ARC_LENGTH_1)
+
+ def test_elliptic_arc_by_external_name_2(self):
+ """ Test 2. Create elliptic arc by name of external edge (reversed)
+ """
+ self.myEllipse = self.mySketch.addEllipticArc("Sketch_1/SketchEllipticArc_2")
+ model.do()
+
+ # check ellipse parameters
+ anArcEdge = self.myEllipse.defaultResult().shape().edge()
+ anEllipse = anArcEdge.ellipse()
+ self.checkPointsEqual(anEllipse.center(), CENTER_POINT)
+ self.checkPointsEqual(self.myEllipse.majorAxisPositive(), MAJOR_AXIS_POINT)
+ self.checkPointsEqual(anArcEdge.firstPoint(), END_POINT)
+ self.checkPointsEqual(anArcEdge.lastPoint(), START_POINT)
+ self.assertAlmostEqual(anArcEdge.length(), ARC_LENGTH_2)
+
+ def test_elliptic_arc_by_external_selection_1(self):
+ """ Test 3. Create elliptic arc by selected edge (direct)
+ """
+ self.myEllipse = self.mySketch.addEllipticArc(ELLIPTIC_ARC_1.results()[-1])
+ model.do()
+
+ # check ellipse parameters
+ anArcEdge = self.myEllipse.defaultResult().shape().edge()
+ anEllipse = anArcEdge.ellipse()
+ self.checkPointsEqual(anEllipse.center(), CENTER_POINT)
+ self.checkPointsEqual(self.myEllipse.majorAxisPositive(), MAJOR_AXIS_POINT)
+ self.checkPointsEqual(self.myEllipse.startPoint(), START_POINT)
+ self.checkPointsEqual(self.myEllipse.endPoint(), END_POINT)
+ self.assertAlmostEqual(anArcEdge.length(), ARC_LENGTH_1)
+
+ def test_elliptic_arc_by_external_selection_2(self):
+ """ Test 4. Create elliptic arc by selected edge (reversed)
+ """
+ self.myEllipse = self.mySketch.addEllipticArc(ELLIPTIC_ARC_2.results()[-1])
+ model.do()
+
+ # check ellipse parameters
+ anArcEdge = self.myEllipse.defaultResult().shape().edge()
+ anEllipse = anArcEdge.ellipse()
+ self.checkPointsEqual(anEllipse.center(), CENTER_POINT)
+ self.checkPointsEqual(self.myEllipse.majorAxisPositive(), MAJOR_AXIS_POINT)
+ self.checkPointsEqual(self.myEllipse.startPoint(), END_POINT)
+ self.checkPointsEqual(self.myEllipse.endPoint(), START_POINT)
+ self.assertAlmostEqual(anArcEdge.length(), ARC_LENGTH_2)
+
+
+if __name__ == "__main__":
+ model.begin()
+ aDocument = model.moduleDocument()
+ aSketch = model.addSketch(aDocument, model.defaultPlane("XOY"))
+ aSketch.addEllipticArc(CENTER_POINT, MAJOR_AXIS_POINT, START_POINT, END_POINT, False)
+ model.do()
+
+ ELLIPTIC_ARC_1 = SketchAPI_EllipticArc(model.lastSubFeature(aSketch, "SketchEllipticArc"))
+ ARC_LENGTH_1 = ELLIPTIC_ARC_1.defaultResult().shape().edge().length()
+
+ aSketch.addEllipticArc(CENTER_POINT, MAJOR_AXIS_POINT, START_POINT, END_POINT, True)
+ model.end()
+
+ ELLIPTIC_ARC_2 = SketchAPI_EllipticArc(model.lastSubFeature(aSketch, "SketchEllipticArc"))
+ ARC_LENGTH_2 = ELLIPTIC_ARC_2.defaultResult().shape().edge().length()
+
+ # redefine end point
+ END_POINT = ELLIPTIC_ARC_2.endPoint()
+
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
+ assert model.checkPythonDump()
--- /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 GeomDataAPI import geomDataAPI_Point2D
+from salome.shaper import model
+
+__updated__ = "2019-09-12"
+
+class TestMoveEllipse(unittest.TestCase):
+ def setUp(self):
+ model.begin()
+ self.myDocument = model.moduleDocument()
+ self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY"))
+ self.myCenter = [70., 50.]
+ self.myFocus = [100., 70.]
+ self.myMinorRadius = 20.
+ self.myEllipse = self.mySketch.addEllipse(self.myCenter[0], self.myCenter[1], self.myFocus[0], self.myFocus[1], self.myMinorRadius)
+ self.myDOF = 5
+ model.do()
+ self.checkDOF()
+ self.myMajorRadius = self.myEllipse.majorRadius().value()
+
+ def tearDown(self):
+ self.checkDOF()
+ 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, theEllipse):
+ point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y())
+ firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y())
+ distPF1 = model.distancePointPoint(firstFocus2d, point)
+ secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y())
+ distPF2 = model.distancePointPoint(secondFocus2d, point)
+ self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7 - math.floor(math.log10(theEllipse.majorRadius().value())))
+
+ def fixMajorRadius(self):
+ self.mySketch.setDistance(self.myEllipse.center(), self.myEllipse.majorAxisPositive(), self.myMajorRadius)
+ self.myDOF -= 1
+ model.do()
+ self.checkDOF()
+
+ def fixMinorRadius(self):
+ self.mySketch.setDistance(self.myEllipse.center(), self.myEllipse.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 ellipse
+ """
+ newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), newPosition)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_free_ellipse(self):
+ """ Test 2. Movement of a free ellipse dragging the edge
+ """
+ newPosition = GeomAPI_Pnt2d(120., 90.)
+ self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), self.myCenter)
+ self.checkPointOnEllipse(newPosition, self.myEllipse)
+ self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipse.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[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), newPosition)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipse.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.myEllipse.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipse)
+ self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipse.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[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), newPosition)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_ellipse_fixed_minor_radius(self):
+ """ Test 6. Movement of ellipse with fixed minor radius
+ """
+ self.fixMinorRadius()
+
+ newPosition = GeomAPI_Pnt2d(120., 90.)
+ self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipse)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipse.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.myEllipse.center())
+
+ newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.]
+ self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), self.myCenter)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_ellipse_fixed_center(self):
+ """ Test 8. Movement of ellipse with fixed center
+ """
+ self.fixPoint(self.myEllipse.center())
+
+ newPosition = GeomAPI_Pnt2d(120., 90.)
+ self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipse)
+ self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_center_ellipse_fixed_focus(self):
+ """ Test 9. Movement of central point of ellipse with fixed focus
+ """
+ self.fixPoint(self.myEllipse.firstFocus())
+
+ newPosition = GeomAPI_Pnt2d(self.myCenter[0] + 20., self.myCenter[1] + 10.)
+ self.mySketch.move(self.myEllipse.center(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), newPosition)
+ self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus)
+ self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipse.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)
+ """
+ self.fixPoint(self.myEllipse.firstFocus())
+
+ newPosition = GeomAPI_Pnt2d(self.myFocus[0] + 10., self.myFocus[1] + 10.)
+ self.mySketch.move(self.myEllipse.firstFocus(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_ellipse_fixed_focus(self):
+ """ Test 11. Movement of ellipse with fixed focus
+ """
+ self.fixPoint(self.myEllipse.firstFocus())
+
+ newPosition = GeomAPI_Pnt2d(80., 90.)
+ self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y())
+ model.do()
+ self.checkPointOnEllipse(newPosition, self.myEllipse)
+ self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus)
+ self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+ self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius)
+
+ def test_move_fixed_ellipse(self):
+ """ Test 12. Trying to move fully fixed ellipse
+ """
+ self.mySketch.setFixed(self.myEllipse.results()[-1])
+ self.myDOF -= 5
+ model.do()
+ self.checkDOF()
+
+ newPosition = [120., 90.]
+ self.mySketch.move(self.myEllipse.defaultResult(), newPosition[0], newPosition[1])
+ model.do()
+ self.checkPointCoordinates(self.myEllipse.center(), self.myCenter)
+ self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus)
+ self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius)
+
+
+if __name__ == "__main__":
+ test_program = unittest.main(exit=False)
+ assert test_program.result.wasSuccessful(), "Test failed"
+ assert(model.checkPythonDump())
assert(featureToPresentation(SketchMultiTranslation_1.feature()).getAISObject(None) is not None)
assert(featureToPresentation(SketchMultiRotation_1.feature()).getAISObject(None) is not None)
+model.end()
+
# Test presentation for Fillet on low-level
aSession = ModelAPI_Session.get()
aSketchFeature = featureToCompositeFeature(Sketch_1.feature())
assert(featureToPresentation(anArc).getAISObject(None) is not None)
aSession.finishOperation()
-model.end()
+# Test presentation for MacroEllipse on low-level
+aSession.startOperation()
+anEllipse = aSketchFeature.addFeature("SketchMacroEllipse")
+anEllipsePnt1 = geomDataAPI_Point2D(anEllipse.attribute("first_point"))
+anEllipsePnt2 = geomDataAPI_Point2D(anEllipse.attribute("second_point"))
+anEllipsePnt3 = geomDataAPI_Point2D(anEllipse.attribute("passed_point"))
+anEllipseType = anEllipse.string("ellipse_type")
+anEllipseType.setValue("by_center_axis_point")
+anEllipsePnt1.setValue(10, 0)
+anEllipsePnt2.setValue(-10, 0)
+anEllipsePnt3.setValue(0, 5)
+assert(featureToPresentation(anEllipse).getAISObject(None) is not None)
+aSession.finishOperation()
+
+# Test presentation for MacroEllipticArc on low-level
+aSession.startOperation()
+anEllipticArc = aSketchFeature.addFeature("SketchMacroEllipticArc")
+anEllipticArcPnt1 = geomDataAPI_Point2D(anEllipticArc.attribute("center"))
+anEllipticArcPnt2 = geomDataAPI_Point2D(anEllipticArc.attribute("major_axis_point"))
+anEllipticArcPnt3 = geomDataAPI_Point2D(anEllipticArc.attribute("start_point"))
+anEllipticArcPnt4 = geomDataAPI_Point2D(anEllipticArc.attribute("end_point"))
+anEllipticArcPnt1.setValue(0, 0)
+anEllipticArcPnt2.setValue(10, 0)
+anEllipticArcPnt3.setValue(0, 5)
+anEllipticArcPnt4.setValue(-10, 0)
+assert(featureToPresentation(anEllipticArc).getAISObject(None) is not None)
+aSession.finishOperation()
--- /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()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_1.addCircle(0, -100, 20)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 20)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchCircle_1.center(), SketchAPI_Line(SketchLine_1).startPoint(), 100, True)
+model.do()
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), model.selection("EDGE", "PartSet/OX"), 30)
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.standardPlane("XOY"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"), True)
+SketchCircle_2 = SketchProjection_2.createdFeature()
+model.do()
+Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_3 = Sketch_3.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face]"), True)
+SketchEllipse_1 = SketchProjection_3.createdFeature()
+SketchProjection_4 = Sketch_3.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"), True)
+SketchEllipse_2 = SketchProjection_4.createdFeature()
+model.do()
+model.end()
+
+from GeomAPI import *
+
+ellipse1 = SketchEllipse_1.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse1.isEdge() and ellipse1.edge().isEllipse())
+ellipse2 = SketchEllipse_2.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse2.isEdge() and ellipse2.edge().isEllipse())
+
+# TODO [limitation]: projection of an ellipse to non-parallel plane is forbiden (OCCT issue #31016)
+assert(Sketch_2.feature().error() != "")
+
+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 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("EDGE", "PartSet/OY"), False)
+SketchLine_1 = SketchProjection_1.createdFeature()
+SketchLine_2 = Sketch_1.addLine(-17.32050807568878, -110, 0, -100)
+SketchLine_3 = Sketch_1.addLine(0, -100, 10, -117.3205080756888)
+SketchArc_1 = Sketch_1.addArc(0, -100, 10, -117.3205080756888, -17.32050807568878, -110, False)
+SketchConstraintRadius_1 = Sketch_1.setRadius(SketchArc_1.results()[1], 20)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_1.result())
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchArc_1.center(), SketchAPI_Line(SketchLine_1).startPoint(), 100, True)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_2.endPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchArc_1.center(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchArc_1.startPoint())
+SketchConstraintPerpendicular_1 = Sketch_1.setPerpendicular(SketchLine_2.result(), SketchLine_3.result())
+SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_3.result(), SketchLine_1.result(), 150)
+model.do()
+Plane_4 = model.addPlane(Part_1_doc, model.selection("FACE", "PartSet/XOZ"), model.selection("EDGE", "PartSet/OX"), 30)
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("COMPOUND", "Sketch_1")], model.selection(), model.selection("FACE", "Plane_1"), 0, model.selection(), 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Plane_1"))
+SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/To_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchArc_1_2]"), True)
+SketchEllipticArc_1 = SketchProjection_2.createdFeature()
+SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/From_Face][Extrusion_1_1/Generated_Face&Sketch_1/SketchArc_1_2]"), True)
+SketchEllipticArc_2 = SketchProjection_3.createdFeature()
+model.do()
+model.end()
+
+from GeomAPI import *
+
+ellipse1 = SketchEllipticArc_1.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse1.isEdge() and ellipse1.edge().isEllipse())
+ellipse2 = SketchEllipticArc_2.results()[-1].resultSubShapePair()[0].shape()
+assert(ellipse2.isEdge() and ellipse2.edge().isEllipse())
+
+assert(model.checkPythonDump())
# Test projection to slope side face of the prism
Sketch_8 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/Generated_Face&Sketch_2/SketchLine_2"))
-aFailedIDs = set([0, 1])
+aFailedIDs = set()
testProjections(Part_1_doc, Sketch_8, aProjectedList, aFailedIDs)
model.end()
--- /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 removing ellipse and its construstion elements
+"""
+
+from salome.shaper import model
+from ModelAPI import *
+
+def assertNbSubs(theSketch, theNbPoints, theNbLines, theNbEllipses, theNbInternalConstraints):
+ model.testNbSubFeatures(theSketch, "SketchPoint", theNbPoints)
+ model.testNbSubFeatures(theSketch, "SketchLine", theNbLines)
+ model.testNbSubFeatures(theSketch, "SketchEllipse", theNbEllipses)
+ model.testNbSubFeatures(theSketch, "SketchConstraintCoincidenceInternal", theNbInternalConstraints)
+
+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"))
+SketchEllipse_1 = Sketch_1.addEllipse(40, 30, 70, 40, 20)
+[Center, Focus1, Focus2, MajorAxisStart, MajorAxisEnd, MinorAxisStart, MinorAxisEnd, MajorAxisLine, MinorAxisLine] = SketchEllipse_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+model.do()
+model.end()
+
+DEFAULT_DOF = 5
+DEFAULT_POINTS = 7
+DEFAULT_LINES = 2
+DEFAULT_ELLIPSES = 1
+DEAFULT_INTERNALS = 11
+
+assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPSES, DEAFULT_INTERNALS)
+assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 1. Remove auxiliary points one by one.
+points = [Center, Focus1, Focus2, MajorAxisStart, MajorAxisEnd, MinorAxisStart, MinorAxisEnd]
+for pnt in points:
+ model.begin()
+ removeFeaturesAndReferences(FeatureSet([pnt.feature()]))
+ model.end()
+
+ assertNbSubs(Sketch_1, DEFAULT_POINTS - 1, DEFAULT_LINES, DEFAULT_ELLIPSES, DEAFULT_INTERNALS - 1)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+ model.undo()
+ assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPSES, DEAFULT_INTERNALS)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 2. Remove auxiliary axes one by one.
+lines = [MajorAxisLine, MinorAxisLine]
+for ln in lines:
+ model.begin()
+ removeFeaturesAndReferences(FeatureSet([ln.feature()]))
+ model.end()
+
+ assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES - 1, DEFAULT_ELLIPSES, DEAFULT_INTERNALS - 2)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+ model.undo()
+ assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPSES, DEAFULT_INTERNALS)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 3. Remove the ellipse.
+model.begin()
+removeFeaturesAndReferences(FeatureSet([SketchEllipse_1.feature()]))
+model.end()
+
+assertNbSubs(Sketch_1, 0, 0, 0, 0)
+assert(model.dof(Sketch_1) == 0)
+model.undo()
+assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPSES, DEAFULT_INTERNALS)
+assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 4. Remove some construction elements, make non-auxiliary a couple of the rest and check the dumping.
+model.begin()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchEllipse_2 = Sketch_2.addEllipse(40, -30, 70, 0, 10)
+[Center, Focus1, Focus2, MajorAxisStart, MajorAxisEnd, MinorAxisStart, MinorAxisEnd, MajorAxisLine, MinorAxisLine] = SketchEllipse_2.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+model.do()
+model.end()
+
+model.begin()
+removeFeaturesAndReferences(FeatureSet([MajorAxisLine.feature(), Focus2.feature()]))
+Focus1.setAuxiliary(False)
+MinorAxisEnd.setAuxiliary(False)
+model.end()
+
+assertNbSubs(Sketch_2, DEFAULT_POINTS - 1, DEFAULT_LINES - 1, DEFAULT_ELLIPSES, DEAFULT_INTERNALS - 3)
+assert(model.dof(Sketch_2) == DEFAULT_DOF)
+
+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 removing elliptic arc and its construstion elements
+"""
+
+from salome.shaper import model
+from ModelAPI import *
+
+def assertNbSubs(theSketch, theNbPoints, theNbLines, theNbEllipticArcs, theNbInternalConstraints):
+ model.testNbSubFeatures(theSketch, "SketchPoint", theNbPoints)
+ model.testNbSubFeatures(theSketch, "SketchLine", theNbLines)
+ model.testNbSubFeatures(theSketch, "SketchEllipticArc", theNbEllipticArcs)
+ model.testNbSubFeatures(theSketch, "SketchConstraintCoincidenceInternal", theNbInternalConstraints)
+
+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"))
+SketchEllipticArc_1 = Sketch_1.addEllipticArc(40, 30, 70, 60, 60, 65, 60., 23.3257583582, False)
+[Center, Focus1, Focus2, MajorAxisStart, MajorAxisEnd, MinorAxisStart, MinorAxisEnd, MajorAxisLine, MinorAxisLine] = SketchEllipticArc_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+model.do()
+model.end()
+
+DEFAULT_DOF = 7
+DEFAULT_POINTS = 7
+DEFAULT_LINES = 2
+DEFAULT_ELLIPTIC_ARCS = 1
+DEAFULT_INTERNALS = 11
+
+assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS)
+assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 1. Remove auxiliary points one by one.
+points = [Center, Focus1, Focus2, MajorAxisStart, MajorAxisEnd, MinorAxisStart, MinorAxisEnd]
+for pnt in points:
+ model.begin()
+ removeFeaturesAndReferences(FeatureSet([pnt.feature()]))
+ model.end()
+
+ assertNbSubs(Sketch_1, DEFAULT_POINTS - 1, DEFAULT_LINES, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS - 1)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+ model.undo()
+ assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 2. Remove auxiliary axes one by one.
+lines = [MajorAxisLine, MinorAxisLine]
+for ln in lines:
+ model.begin()
+ removeFeaturesAndReferences(FeatureSet([ln.feature()]))
+ model.end()
+
+ assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES - 1, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS - 2)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+ model.undo()
+ assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS)
+ assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 3. Remove the elliptic arc.
+model.begin()
+removeFeaturesAndReferences(FeatureSet([SketchEllipticArc_1.feature()]))
+model.end()
+
+assertNbSubs(Sketch_1, 0, 0, 0, 0)
+assert(model.dof(Sketch_1) == 0)
+model.undo()
+assertNbSubs(Sketch_1, DEFAULT_POINTS, DEFAULT_LINES, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS)
+assert(model.dof(Sketch_1) == DEFAULT_DOF)
+
+# Test 4. Remove some construction elements, make non-auxiliary a couple of the rest and check the dumping.
+model.begin()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchEllipticArc_2 = Sketch_2.addEllipticArc(40, -30, 70, 0, 30, 10, 0, -20, True)
+[Center, Focus1, Focus2, MajorAxisStart, MajorAxisEnd, MinorAxisStart, MinorAxisEnd, MajorAxisLine, MinorAxisLine] = SketchEllipticArc_2.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+SketchEllipticArc_2.setAuxiliary(True)
+model.do()
+model.end()
+
+model.begin()
+removeFeaturesAndReferences(FeatureSet([MajorAxisLine.feature(), Focus2.feature()]))
+Focus1.setAuxiliary(False)
+MinorAxisLine.setAuxiliary(False)
+model.end()
+
+assertNbSubs(Sketch_2, DEFAULT_POINTS - 1, DEFAULT_LINES - 1, DEFAULT_ELLIPTIC_ARCS, DEAFULT_INTERNALS - 3)
+assert(model.dof(Sketch_2) == DEFAULT_DOF)
+
+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 salome.shaper import geom
+import math
+
+from ModelAPI import *
+from SketchAPI import *
+
+CENTER = geom.Pnt2d(10, 10)
+MAJOR_RADIUS = 50
+MINOR_RADIUS = 30
+
+DOF = 11
+NB_LINES = 3
+NB_ELLIPSES = 1
+NB_ELLIPTIC_ARCS = 0
+NB_COINCIDENCES = 5
+
+TOLERANCE = 1.e-6
+
+def checkFeaturesQuantity(theSketch):
+ model.testNbSubFeatures(theSketch, "SketchLine", NB_LINES)
+ model.testNbSubFeatures(theSketch, "SketchEllipse", NB_ELLIPSES)
+ model.testNbSubFeatures(theSketch, "SketchEllipticArc", NB_ELLIPTIC_ARCS)
+ model.testNbSubFeatures(theSketch, "SketchConstraintCoincidence", NB_COINCIDENCES)
+ assert(model.dof(theSketch) == DOF)
+
+def checkEllipticArcs(theSketch):
+ for aSub in theSketch.features().list():
+ aFeature = ModelAPI_Feature.feature(aSub)
+ if aFeature is not None and aFeature.getKind() == "SketchEllipticArc":
+ assertEllipticArc(SketchAPI_EllipticArc(aFeature))
+
+def assertEllipticArc(theArc):
+ assertPoints(theArc.center(), CENTER)
+ assertPoints(theArc.majorAxisPositive(), geom.Pnt2d(CENTER.x() + MAJOR_RADIUS, CENTER.y()))
+ assertPoints(theArc.minorAxisPositive(), geom.Pnt2d(CENTER.x(), CENTER.y() + MINOR_RADIUS))
+
+def assertPoints(thePoint1, thePoint2):
+ assert(math.fabs(thePoint1.x() - thePoint2.x()) < TOLERANCE), "{} != {}".format(thePoint1.x(), thePoint2.x())
+ assert(math.fabs(thePoint1.y() - thePoint2.y()) < TOLERANCE), "{} != {}".format(thePoint1.y(), thePoint2.y())
+
+
+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"))
+SketchEllipse_1 = Sketch_1.addEllipse(CENTER.x(), CENTER.y(), CENTER.x() + math.sqrt(MAJOR_RADIUS**2 - MINOR_RADIUS**2), CENTER.y(), MINOR_RADIUS)
+SketchLine_1 = Sketch_1.addLine(-16.74176451428603, -15.34869012470842, -16.85909682653373, 35.30399198463829)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchEllipse_1.result())
+SketchLine_2 = Sketch_1.addLine(-16.85909682653373, 35.30399198463829, 20.9032928583277, -19.27802168426675)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchEllipse_1.result())
+SketchLine_3 = Sketch_1.addLine(34.69765676551338, 36.08465583643841, 35.0422024535432, -15.96612629290852)
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.startPoint(), SketchEllipse_1.result())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchEllipse_1.result())
+model.do()
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+# split the ellipse
+SketchSplit = Sketch_1.addSplit(SketchEllipse_1, geom.Pnt2d(CENTER.x() + MAJOR_RADIUS, CENTER.y()))
+model.do()
+NB_ELLIPSES -= 1
+NB_ELLIPTIC_ARCS += 2
+NB_COINCIDENCES += 4
+DOF += 3
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+# split the middle arc of ellipse
+EllipticArc = SketchAPI_EllipticArc(model.lastSubFeature(Sketch_1, "SketchEllipticArc"))
+ANGLE = -math.pi/2 - math.pi/10
+SketchSplit = Sketch_1.addSplit(EllipticArc, geom.Pnt2d(CENTER.x() + MAJOR_RADIUS * math.cos(ANGLE), CENTER.y() + MINOR_RADIUS * math.sin(ANGLE)))
+model.do()
+NB_ELLIPTIC_ARCS += 2
+NB_COINCIDENCES += 4
+DOF += 8
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+# try to split the boundary arc of ellipse,
+# it shoult fail, because there is no coincident points
+EllipticArc = SketchAPI_EllipticArc(model.lastSubFeature(Sketch_1, "SketchEllipticArc"))
+SketchSplit = Sketch_1.addSplit(EllipticArc, geom.Pnt2d(CENTER.x() - MAJOR_RADIUS, CENTER.y()))
+model.end()
+aValidators = ModelAPI_Session.get().validators()
+assert(not aValidators.validate(SketchSplit.feature()))
+
+# remove previous split and add coincidence
+model.undo()
+model.begin()
+Part_1_doc.removeFeature(SketchSplit.feature())
+model.do()
+Sketch_1.setCoincident(SketchLine_1.endPoint(), EllipticArc.result())
+Sketch_1.setCoincident(SketchLine_2.startPoint(), EllipticArc.result())
+model.do()
+NB_COINCIDENCES += 1
+DOF -= 1
+
+# split the boundary arc of ellipse
+SketchSplit = Sketch_1.addSplit(EllipticArc, geom.Pnt2d(CENTER.x() - MAJOR_RADIUS, CENTER.y()))
+model.do()
+NB_ELLIPTIC_ARCS += 1
+NB_COINCIDENCES += 4
+DOF += 4
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+model.end()
+
+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 salome.shaper import geom
+import math
+
+from ModelAPI import *
+from SketchAPI import *
+
+CENTER = geom.Pnt2d(10, 10)
+MAJOR_RADIUS = 50
+MINOR_RADIUS = 30
+
+DOF = 11
+NB_LINES = 3
+NB_ELLIPSES = 1
+NB_ELLIPTIC_ARCS = 0
+NB_COINCIDENCES = 6
+NB_EQUALS = 0
+
+TOLERANCE = 1.e-6
+
+def checkFeaturesQuantity(theSketch):
+ model.testNbSubFeatures(theSketch, "SketchLine", NB_LINES)
+ model.testNbSubFeatures(theSketch, "SketchEllipse", NB_ELLIPSES)
+ model.testNbSubFeatures(theSketch, "SketchEllipticArc", NB_ELLIPTIC_ARCS)
+ model.testNbSubFeatures(theSketch, "SketchConstraintCoincidence", NB_COINCIDENCES)
+ model.testNbSubFeatures(theSketch, "SketchConstraintEqual", NB_EQUALS)
+ assert(model.dof(theSketch) == DOF)
+
+def checkEllipticArcs(theSketch):
+ for aSub in theSketch.features().list():
+ aFeature = ModelAPI_Feature.feature(aSub)
+ if aFeature is not None and aFeature.getKind() == "SketchEllipticArc":
+ assertEllipticArc(SketchAPI_EllipticArc(aFeature))
+
+def assertEllipticArc(theArc):
+ assertPoints(theArc.center(), CENTER)
+ assertPoints(theArc.majorAxisPositive(), geom.Pnt2d(CENTER.x() + MAJOR_RADIUS, CENTER.y()))
+ assertPoints(theArc.minorAxisPositive(), geom.Pnt2d(CENTER.x(), CENTER.y() + MINOR_RADIUS))
+
+def assertPoints(thePoint1, thePoint2):
+ assert(math.fabs(thePoint1.x() - thePoint2.x()) < TOLERANCE), "{} != {}".format(thePoint1.x(), thePoint2.x())
+ assert(math.fabs(thePoint1.y() - thePoint2.y()) < TOLERANCE), "{} != {}".format(thePoint1.y(), thePoint2.y())
+
+
+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"))
+SketchEllipse_1 = Sketch_1.addEllipse(CENTER.x(), CENTER.y(), CENTER.x() + math.sqrt(MAJOR_RADIUS**2 - MINOR_RADIUS**2), CENTER.y(), MINOR_RADIUS)
+SketchLine_1 = Sketch_1.addLine(-16.74176451428603, -15.34869012470842, -16.85909682653373, 35.30399198463829)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchEllipse_1.result())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchEllipse_1.result())
+SketchLine_2 = Sketch_1.addLine(-16.85909682653373, 35.30399198463829, 20.9032928583277, -19.27802168426675)
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_2.startPoint(), SketchEllipse_1.result())
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchEllipse_1.result())
+SketchLine_3 = Sketch_1.addLine(34.69765676551338, 36.08465583643841, 35.0422024535432, -17.96612629290852)
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchLine_3.startPoint(), SketchEllipse_1.result())
+model.do()
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+# trim the ellipse
+SketchSplit = Sketch_1.addTrim(SketchEllipse_1, geom.Pnt2d(CENTER.x() + MAJOR_RADIUS, CENTER.y()))
+model.do()
+NB_ELLIPSES -= 1
+NB_ELLIPTIC_ARCS += 1
+NB_COINCIDENCES += 1
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+# trim the middle arc of ellipse
+EllipticArc = SketchAPI_EllipticArc(model.lastSubFeature(Sketch_1, "SketchEllipticArc"))
+ANGLE = -math.pi/2 - math.pi/10
+SketchSplit = Sketch_1.addTrim(EllipticArc, geom.Pnt2d(CENTER.x() + MAJOR_RADIUS * math.cos(ANGLE), CENTER.y() + MINOR_RADIUS * math.sin(ANGLE)))
+model.do()
+NB_ELLIPTIC_ARCS += 1
+NB_COINCIDENCES += 1
+NB_EQUALS += 1
+DOF += 1
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+# trim the boundary arc of ellipse
+SketchSplit = Sketch_1.addTrim(EllipticArc, geom.Pnt2d(CENTER.x() - MAJOR_RADIUS, CENTER.y()))
+model.do()
+NB_COINCIDENCES -= 1
+DOF += 1
+
+checkFeaturesQuantity(Sketch_1)
+checkEllipticArcs(Sketch_1)
+
+model.end()
+
+assert(model.checkPythonDump())
rectangleFeature.rst
circleFeature.rst
arcFeature.rst
+ ellipseFeature.rst
+ arcEllipseFeature.rst
.. _sketch_constraints:
--- /dev/null
+
+ .. _tui_create_ellipse:
+
+Create Skecth Ellipse
+====================
+
+.. literalinclude:: examples/ellipse.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/ellipse.py>`
--- /dev/null
+
+ .. _tui_create_elliptic_arc:
+
+Create Skecth Elliptic Arc
+==========================
+
+.. literalinclude:: examples/elliptic_arc.py
+ :linenos:
+ :language: python
+
+:download:`Download this script <examples/elliptic_arc.py>`
--- /dev/null
+.. |earc.icon| image:: images/elliptic_arc.png
+
+Elliptic Arc
+============
+
+Elliptic Arc feature creates an elliptic arc segment in the current Sketch.
+
+To add a new Elliptic Arc to the Sketch:
+
+#. select in the Main Menu *Sketch - > Elliptic Arc* item or
+#. click |earc.icon| **Elliptic Arc** button in Sketch toolbar:
+
+The following property panel appears:
+
+.. image:: images/elliptic_arc_panel.png
+ :align: center
+
+Click in the view to set the center point, then move the mouse and click a second time to set a point of a one semi-axis, then click to set a starting point of the arc and then to set an end point of the arc.
+
+**TUI Command**:
+
+.. py:function:: Sketch_1.addEllipticArc(CenterX, CenterY, FocusX, FocusY, StartX, StartY, EndX, EndY, Inversed)
+
+ :param real: Center X.
+ :param real: Center Y.
+ :param real: Focus X.
+ :param real: Focus Y.
+ :param real: Start X.
+ :param real: Start Y.
+ :param real: End X.
+ :param real: End Y.
+ :param boolean: Is inversed.
+ :return: Result object.
+
+Result
+""""""
+
+Created elliptic arc appears in the view.
+
+.. image:: images/elliptic_arc_result.png
+ :align: center
+
+.. centered::
+ Elliptic arc created
+
+**See Also** a sample TUI Script of :ref:`tui_create_elliptic_arc` operation.
\ No newline at end of file
#. select in the Main Menu *Sketch - > Arc* item or
#. click |arc.icon| **Arc** button in Sketch toolbar:
-There are 3 algorithms for creation of an Arc:
+There are 4 algorithms for creation of an Arc:
.. image:: images/arc_base_32x32.png
:align: left
:align: left
**By tangent point and end point** creates an arc segment with the tangent point and the end point.
+.. image:: images/arc_perp_32x32.png
+ :align: left
+**By point on perpendicular line and end point** creates an arc segment perpendicular to a straight line with the start point, connected with boundary of this line, and the end point.
+
By center and two points
""""""""""""""""""""""""
:param real: Passed Y.
:return: Result object.
-By tangent point and point
-""""""""""""""""""""""""""
+By tangent point and end point
+""""""""""""""""""""""""""""""
.. image:: images/Arc_panel_tang.png
:align: center
**TUI Command**:
-.. py:function:: Sketch_1.addArc(TangetPoint, EndX, EndY, Inversed)
+.. py:function:: Sketch_1.addArc(TangentPoint, EndX, EndY, Inversed)
+
+ :param object: Tangent Point.
+ :param real: End X.
+ :param real: End Y.
+ :param boolean: Is inversed.
+ :return: Result object.
+
+By point on perpendicular line and end point
+""""""""""""""""""""""""""""""""""""""""""""
+
+.. image:: images/Arc_panel_perp.png
+ :align: center
+
+Select a point on a straight segment in the view to set the start point, then move the mouse and click to set the end point.
+The edge on which the start point lies will be perpendicular to the arc (the center of the arc is lying on the edge).
+
+- When entering a start point by selecting a point on segment, a Perpendicular constraint is created.
+- When entering an end point by selecting a segment, a Coincident constraint is created.
+- When entering an end point, only segments are selectable.
+
+**TUI Command**:
+
+.. py:function:: Sketch_1.addArc(StartPoint, EndX, EndY, Inversed, True)
- :param object: Tanget Point.
+ :param object: Start Point.
:param real: End X.
:param real: End Y.
:param boolean: Is inversed.
+ :param boolean: Arc is perpendicular (always True).
:return: Result object.
Result
:align: center
.. centered::
- Circle created
+ Arc created
**See Also** a sample TUI Script of :ref:`tui_create_arc` operation.
\ No newline at end of file
+.. |ellipse.icon| image:: images/ellipse.png
- Ellipse
- =======
+Ellipse
+=======
+
+The feature Ellipse creates an ellipse in the current Sketch.
+
+To add a new Ellipse to the Sketch:
+
+#. select in the Main Menu *Sketch - > Ellipse* item or
+#. click |ellipse.icon| **Ellipse** button in Sketch toolbar:
+
+There are 2 algorithms for creation of an Ellipse:
+
+.. image:: images/ellipse_cent_rad_32x32.png
+ :align: left
+**By center and major semi-axes and passing points** creates an ellipse with the given center passing through given points.
+
+.. image:: images/ellipse_axes_32x32.png
+ :align: left
+**By major axis and passing point** creates an ellipse passing through the given three points.
+
+By center and major semi-axes and passing points
+""""""""""""""""""""""""""""""""""""""""""""""""
+
+.. image:: images/ellipse_panel_pt_rad.png
+ :align: center
+
+Click in the view once to set the center point, then move the mouse and click to set a point of a first semi-axis, then again move the mouse to set a point of a second semi-axis.
+
+**TUI Command**:
+
+.. py:function:: Sketch_1.addEllipse(CenterX, CenterY, MajorAxisX, MajorAxisY, PassedX, PassedY, True)
+
+ :param real: Center X.
+ :param real: Center Y.
+ :param real: Major Axis X.
+ :param real: Major Axis Y.
+ :param real: Passed X.
+ :param real: Passed Y.
+ :param boolean: True mentions that the first coordinates define the center of the ellipse.
+ :return: Result object.
+
+By major axis and passing point
+"""""""""""""""""""""""""""""""
+
+.. image:: images/ellipse_panel_3pt.png
+ :align: center
+
+Click in the view once to set a first point of a first axis, then move the mouse and click to set a second point of the first axis, then again move the mouse to set a point of a second semi-axis.
+
+**TUI Command**:
+
+.. py:function:: Sketch_1.addEllipse(MajorAxisStartX, MajorAxisStartY, MajorAxisEndX, MajorAxisEndY, PassedX, PassedY, False)
+
+ :param real: Major Axis Start X.
+ :param real: Major Axis Start Y.
+ :param real: Major Axis End X.
+ :param real: Major Axis End Y.
+ :param real: Passed X.
+ :param real: Passed Y.
+ :param boolean: False mentions that the first coordinates define the start point of major axis of the ellipse.
+ :return: Result object.
+
+Result
+""""""
+
+Created ellipse appears in the view.
+
+.. image:: images/ellipse_result.png
+ :align: center
+
+.. centered::
+ Ellipse created
+
+
+**See Also** a sample TUI Script of :ref:`tui_create_ellipse` operation.
SketchLine_3 = Sketch_1.addLine(25.0, 109.4, 68.1, 153.6)
SketchLine_3.setAuxiliary(True)
SketchArc_3 = Sketch_1.addArc(SketchLine_3.startPoint(), 92.1, 34.0, True)
+SketchArc_4 = Sketch_1.addArc(SketchLine_3.endPoint(), 150.0, 10.0, True, True)
model.do()
model.end()
--- /dev/null
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchEllipse_1 = Sketch_1.addEllipse(-70, 5, -25, 10, -50, 40, True)
+SketchEllipse_2 = Sketch_1.addEllipse(30, 50, 90, 10, 70, 50, False)
+model.do()
+model.end()
--- /dev/null
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Sketch_1 = model.addSketch(partSet, model.defaultPlane("XOY"))
+SketchEllipticArc_1 = Sketch_1.addEllipticArc(-130.9349397590362, 14.84578313253013, -130.1669839639096, 36.73252329363673, -113.8987951807229, 13.87228915662651, -144.7734498958671, 30.30133508641346, False)
+[SketchPoint_1, SketchPoint_2, SketchPoint_3, SketchPoint_4, SketchPoint_5, SketchPoint_6, SketchPoint_7, SketchLine_1, SketchLine_2] = SketchEllipticArc_1.construction(center = "aux", firstFocus = "aux", secondFocus = "aux", majorAxisStart = "aux", majorAxisEnd = "aux", minorAxisStart = "aux", minorAxisEnd = "aux", majorAxis = "aux", minorAxis = "aux")
+model.do()
+model.end()
.. _sketchPerpendicular:
-.. |perpendicular.icon| image:: images/perpendicular.png
+.. |Perpendicular.icon| image:: images/Perpendicular.png
Perpendicular constraint
========================
Perpendicular constraint fixes two lines at 90 degrees to one another.
+For a line and a circle/arc the perpendicular constraint fixes the center of circle/arc to be on a line.
To create a Perpendicular constraint in the active Sketch:
#. select in the Main Menu *Sketch - > Perpendicular* item or
-#. click |perpendicular.icon| **Perpendicular** button in Sketch toolbar:
+#. click |Perpendicular.icon| **Perpendicular** button in Sketch toolbar:
Property panel:
Input fields:
-- **First line** is the first line selected in the view.
-- **Second line** is the second line selected in the view.
+- **First object** is the first line, circle or arc selected in the view.
+- **Second object** is the second line, circle or arc selected in the view.
-After the lines are selected, a special sign will be added to each of them in the view.
+After the objects are selected, a special sign will be added to each of them in the view.
+
+If one of selected objects is circular, then another has to be a straight line.
**TUI Command**:
Created Perpendicular constraint appears in the view.
.. image:: images/Perpendicular_res.png
- :align: center
+ :align: center
.. centered::
Created perpendicular constraint
id="Sketch"
nested="SketchPoint SketchIntersectionPoint SketchLine
SketchCircle SketchMacroCircle SketchArc SketchMacroArc
+ SketchEllipse SketchMacroEllipse SketchEllipticArc SketchMacroEllipticArc
SketchRectangle
SketchProjection
SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintDistanceHorizontal SketchConstraintDistanceVertical
SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical
SketchConstraintEqual SketchConstraintTangent
SketchFillet SketchSplit SketchTrim
- SketchConstraintCoincidence
+ SketchConstraintCoincidence SketchConstraintCoincidenceInternal
SketchConstraintMirror SketchConstraintAngle
SketchMultiRotation SketchMultiTranslation
SketchConstraintCollinear SketchConstraintMiddle"
<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="SolverDOF"/> -->
<label id="SolverError" styleSheet="color : red; font : bold"/>
<validator id="SketchPlugin_SolverErrorValidator"/>
</feature>
enable_value="enable_by_preferences"/>
<sketch-2dpoint_selector id="EndPoint" accept_expressions="0" title="End point" tooltip="End point coordinates"
enable_value="enable_by_preferences"/>
- <labelvalue id="LineLength" accept_expressions="0" label="Length:" default="computed" icon="icons/Sketch/distance_value.png"
+ <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"/>
<validator id="GeomValidators_Different" parameters="StartPoint,EndPoint"/>
</feature>
</group>
- <group id="Circular geometry">
+ <group id="Conical geometry">
<!-- SketchCircle is a hidden feature. It is created inside SketchMacroCircle. -->
<feature id="SketchCircle"
title="Circle"
enable_value="enable_by_preferences"/>
<labelvalue id="circle_radius"
icon="icons/Sketch/radius.png"
- label="Radius:"
+ label="Radius"
tooltip="Set radius"
default="computed"
accept_expressions="0"
</toolbox>
<labelvalue id="circle_radius"
icon="icons/Sketch/radius.png"
- label="Radius:"
+ label="Radius"
tooltip="Set radius"
default="computed"
accept_expressions="0"
obligatory="0"
enable_value="enable_by_preferences">
- <validator id="GeomValidators_Positive"/>
</labelvalue>
<boolvalue id="Auxiliary"
tooltip="Construction element"
<validator id="GeomValidators_Different" parameters="center_point,start_point,end_point"/>
<labelvalue id="radius"
icon="icons/Sketch/radius.png"
- label="Radius:"
+ label="Radius"
tooltip="Set radius"
accept_expressions="0"
min="0"
</labelvalue>
<labelvalue id="angle"
icon="icons/Sketch/angle.png"
- label="Angle:"
+ label="Angle"
tooltip="Set angle"
default="0"
use_reset="false"
<validator id="SketchPlugin_ArcEndPointValidator" parameters="end_point_ref"/>
</sketch-2dpoint_selector>
</box>
+ <box id="by_transversal_line"
+ icon="icons/Sketch/arc_perp_32x32.png"
+ title="Perpendicular to line">
+ <sketch_shape_selector id="tangent_point"
+ label="Point on the perpendicular line"
+ tooltip="Select point on line"
+ shape_types="vertex">
+ <validator id="SketchPlugin_ArcTransversalPoint"/>
+ </sketch_shape_selector>
+ <sketch-2dpoint_selector id="end_point_3"
+ reference_attribute="end_point_ref"
+ title="End point"
+ tooltip="End point"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ <validator id="SketchPlugin_ArcEndPointValidator" parameters="end_point_ref"/>
+ </sketch-2dpoint_selector>
+ </box>
</toolbox>
<labelvalue id="radius"
icon="icons/Sketch/radius.png"
- label="Radius:"
+ label="Radius"
tooltip="Set radius"
accept_expressions="0"
min="0"
</labelvalue>
<labelvalue id="angle"
icon="icons/Sketch/angle.png"
- label="Angle:"
+ label="Angle"
tooltip="Set angle"
default="0"
use_reset="false"
</sketch_shape_selector>
<!--<validator id="PartSet_FilletSelection"/>-->
</feature>
- <!-- SketchSplit -->
- <feature id="SketchSplit" title="Split"
- tooltip="Cut selected segment arc or circle on existing coincident points"
- icon="icons/Sketch/split.png"
- helpfile="splitFeature.html">
- <sketch_feature_point_selector
- id="SelectedObject"
- selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
- label="Segment"
- tooltip="Select segment for split"
- shape_types="edge"
- use_external="false">
- <validator id="SketchPlugin_SplitValidator"/>
- </sketch_feature_point_selector>
- <validator id="PartSet_SplitSelection"/>
- </feature>
- <!-- SketchTrim -->
- <feature id="SketchTrim" title="Trim"
- tooltip="Trim selected segment arc or circle on intersection points nearest to the graphic selection"
- icon="icons/Sketch/trim.png"
- helpfile="trimFeature.html">
- <sketch_feature_point_selector
- id="SelectedObject"
- selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
- label="Segment"
- tooltip="Select segment for trim"
- shape_types="edge"
- use_external="false">
- <validator id="SketchPlugin_TrimValidator"/>
- </sketch_feature_point_selector>
- <validator id="PartSet_SplitSelection"/>
- </feature>
- </group>
-<excluded>
- <group id="Elliptic geometry">
<!-- SketchEllipse is a hidden feature. It is created inside SketchMacroEllipse. -->
<feature id="SketchEllipse"
title="Ellipse"
tooltip="Center coordinates"
accept_expressions="0"
enable_value="enable_by_preferences"/>
- <sketch-2dpoint_selector id="ellipse_focus"
- title="Focus"
+ <sketch-2dpoint_selector id="ellipse_first_focus"
+ title="First focus"
tooltip="Focus coordinates"
accept_expressions="0"
enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_second_focus"
+ title="Second focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_start_point"
+ title="Major axis start"
+ tooltip="Coordinates of point on negative direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_end_point"
+ title="Major axis end"
+ tooltip="Coordinates of point on positive direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_start_point"
+ title="Minor axis start"
+ tooltip="Coordinates of point on negative direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_end_point"
+ title="Minor axis end"
+ tooltip="Coordinates of point on positive direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
<labelvalue id="ellipse_major_radius"
- icon="icons/Sketch/radius.png"
- label="Major radius:"
+ icon="icons/Sketch/radius_major.png"
+ label="Major radius"
tooltip="Set major radius"
default="computed"
accept_expressions="0"
enable_value="enable_by_preferences">
</labelvalue>
<labelvalue id="ellipse_minor_radius"
- icon="icons/Sketch/radius.png"
- label="Minor radius:"
+ icon="icons/Sketch/radius_minor.png"
+ label="Minor radius"
tooltip="Set minor radius"
default="computed"
accept_expressions="0"
title="Ellipse"
tooltip="Create ellipse"
helpfile="ellipseFeature.html">
- <sketch-2dpoint_selector id="center_point"
- reference_attribute="center_point_ref"
+ <toolbox id="ellipse_type" modified_in_edit="edit_ellipse_type">
+ <box id="by_center_axis_point"
+ icon="icons/Sketch/ellipse_cent_rad_32x32.png"
+ title="Center, major semi-axis and passing point">
+ <sketch-2dpoint_selector id="first_point"
+ reference_attribute="first_point_ref"
+ title="Center point"
+ tooltip="Center point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="second_point"
+ reference_attribute="second_point_ref"
+ title="Major axis point"
+ tooltip="Major axis point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="passed_point"
+ reference_attribute="passed_point_ref"
+ title="Passed point"
+ tooltip="Passed point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ </box>
+ <box id="by_major_axis_and_point"
+ icon="icons/Sketch/ellipse_axes_32x32.png"
+ title="Major axis and passing point">
+ <sketch-2dpoint_selector id="first_point_1"
+ reference_attribute="first_point_ref_1"
+ title="Major axis start point"
+ tooltip="Major axis start point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="second_point_1"
+ reference_attribute="second_point_ref_1"
+ title="Major axis end point"
+ tooltip="Major axis end point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="passed_point_1"
+ reference_attribute="passed_point_ref_1"
+ title="Passed point"
+ tooltip="Passed point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ </box>
+ </toolbox>
+ <labelvalue id="major_radius"
+ icon="icons/Sketch/radius_major.png"
+ label="Major radius"
+ tooltip="Set major radius"
+ default="computed"
+ accept_expressions="0"
+ obligatory="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <labelvalue id="minor_radius"
+ icon="icons/Sketch/radius_minor.png"
+ label="Minor radius"
+ tooltip="Set minor radius"
+ default="computed"
+ accept_expressions="0"
+ obligatory="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <boolvalue id="Auxiliary"
+ tooltip="Construction element"
+ label="Auxiliary"
+ default="false"
+ obligatory="0"/>
+ </feature>
+
+ <!-- SketchEllipticArc is a hidden feature. It is created inside SketchMacroEllipse. -->
+ <feature id="SketchEllipticArc"
+ title="Elliptic arc"
+ tooltip="Create elliptic arc"
+ icon="icons/Sketch/elliptic_arc.png"
+ internal="1">
+ <sketch-2dpoint_selector id="ellipse_center"
+ title="Center"
+ tooltip="Center coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_first_focus"
+ title="First focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_second_focus"
+ title="Second focus"
+ tooltip="Focus coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_start_point"
+ title="Major axis start"
+ tooltip="Coordinates of point on negative direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_major_axis_end_point"
+ title="Major axis end"
+ tooltip="Coordinates of point on positive direction of major axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_start_point"
+ title="Minor axis start"
+ tooltip="Coordinates of point on negative direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="ellipse_minor_axis_end_point"
+ title="Minor axis end"
+ tooltip="Coordinates of point on positive direction of minor axis"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="start_point"
+ title="Start point"
+ tooltip="Arc start point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="end_point"
+ title="End point"
+ tooltip="Arc end point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <labelvalue id="ellipse_major_radius"
+ icon="icons/Sketch/radius_major.png"
+ label="Major radius"
+ tooltip="Set major radius"
+ default="computed"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <labelvalue id="ellipse_minor_radius"
+ icon="icons/Sketch/radius_minor.png"
+ label="Minor radius"
+ tooltip="Set minor radius"
+ default="computed"
+ accept_expressions="0"
+ enable_value="enable_by_preferences">
+ </labelvalue>
+ <boolvalue id="Auxiliary" label="Auxiliary" default="false" tooltip="Construction element" obligatory="0"/>
+ </feature>
+ <!-- SketchMacroEllipticArc -->
+ <feature id="SketchMacroEllipticArc"
+ icon="icons/Sketch/elliptic_arc.png"
+ title="Elliptic arc"
+ tooltip="Create elliptic arc"
+ helpfile="ellipseFeature.html">
+ <sketch-2dpoint_selector id="center"
+ reference_attribute="center_ref"
title="Center point"
tooltip="Center point coordinates"
accept_expressions="0"
tooltip="Major axis point coordinates"
accept_expressions="0"
enable_value="enable_by_preferences"/>
- <sketch-2dpoint_selector id="passed_point"
- reference_attribute="passed_point_ref"
- title="Passed point"
- tooltip="Passed point coordinates"
+ <sketch-2dpoint_selector id="start_point"
+ reference_attribute="start_point_ref"
+ title="Start point"
+ tooltip="Arc start point coordinates"
accept_expressions="0"
- enable_value="enable_by_preferences">
-<!-- <validator id="SketchPlugin_CirclePassedPointValidator"/> -->
- </sketch-2dpoint_selector>
-<!-- <validator id="GeomValidators_Different" parameters="center_point_ref,passed_point_ref"/> -->
- <labelvalue id="ellipse_major_radius"
- icon="icons/Sketch/radius.png"
- label="Major radius:"
+ enable_value="enable_by_preferences"/>
+ <sketch-2dpoint_selector id="end_point"
+ reference_attribute="end_point_ref"
+ title="End point"
+ tooltip="Arc end point coordinates"
+ accept_expressions="0"
+ enable_value="enable_by_preferences"/>
+ <labelvalue id="major_radius"
+ icon="icons/Sketch/radius_major.png"
+ label="Major radius"
tooltip="Set major radius"
default="computed"
accept_expressions="0"
obligatory="0"
enable_value="enable_by_preferences">
- <validator id="GeomValidators_Positive"/>
</labelvalue>
- <labelvalue id="ellipse_minor_radius"
- icon="icons/Sketch/radius.png"
- label="Minor radius:"
+ <labelvalue id="minor_radius"
+ icon="icons/Sketch/radius_minor.png"
+ label="Minor radius"
tooltip="Set minor radius"
default="computed"
accept_expressions="0"
obligatory="0"
enable_value="enable_by_preferences">
- <validator id="GeomValidators_Positive"/>
</labelvalue>
<boolvalue id="Auxiliary"
tooltip="Construction element"
obligatory="0"/>
</feature>
</group>
-</excluded>
+
+ <group id="Segmentation">
+ <!-- SketchSplit -->
+ <feature id="SketchSplit" title="Split"
+ tooltip="Cut selected segment arc or circle on existing coincident points"
+ icon="icons/Sketch/split.png"
+ helpfile="splitFeature.html">
+ <sketch_feature_point_selector
+ id="SelectedObject"
+ selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
+ label="Segment"
+ tooltip="Select segment for split"
+ shape_types="edge"
+ use_external="false">
+ <validator id="SketchPlugin_SplitValidator"/>
+ </sketch_feature_point_selector>
+ <validator id="PartSet_SplitSelection"/>
+ </feature>
+ <!-- SketchTrim -->
+ <feature id="SketchTrim" title="Trim"
+ tooltip="Trim selected segment arc or circle on intersection points nearest to the graphic selection"
+ icon="icons/Sketch/trim.png"
+ helpfile="trimFeature.html">
+ <sketch_feature_point_selector
+ id="SelectedObject"
+ selection_attributes="SelectedObject SelectedPoint PreviewObject PreviewPoint"
+ label="Segment"
+ tooltip="Select segment for trim"
+ shape_types="edge"
+ use_external="false">
+ <validator id="SketchPlugin_TrimValidator"/>
+ </sketch_feature_point_selector>
+ <validator id="PartSet_SplitSelection"/>
+ </feature>
+ </group>
<group id="Projection">
<!-- Projected feature -->
<validator id="SketchPlugin_ReplicationReference" parameters="ConstraintEntityC"/>
</sketch_shape_selector>
<sketch_multi_selector id="ConstraintMirrorList"
- label="Segments:"
+ label="Segments"
tooltip="Select list of objects to be mirrored"
shape_types="Edges"
use_external="true"
tooltip="Copy objects and move"
helpfile="translationFeature.html">
<sketch_multi_selector id="MultiTranslationList"
- label="Segments:"
+ label="Segments"
tooltip="Select list of objects to be translated"
shape_types="Edges"
use_external="true"
tooltip="Copy objects and rotate"
helpfile="rotationFeature.html">
<sketch_multi_selector id="MultiRotationList"
- label="Segments:"
+ label="Segments"
tooltip="Select list of objects to be rotated"
shape_types="Edges"
use_external="true"
</group>
<group id="Dimensional constraints">
- <!-- SketchConstraintDistance -->
+ <!-- SketchConstraintDistance -->
<feature
id="SketchConstraintDistance"
title="Distance"
<feature id="SketchConstraintRigid" title="Fixed" tooltip="Fix an object" icon="icons/Sketch/fixed.png"
helpfile="rigidFeature.html">
<sketch_shape_selector id="ConstraintEntityA" label="Object"
- tooltip="Select point, line end point, line, center of circle or arc."
+ tooltip="Select point, curve or its boundary point."
shape_types="edge vertex">
- <validator id="GeomValidators_ShapeType" parameters="vertex,line,circle"/>
+ <validator id="GeomValidators_ShapeType" parameters="vertex,edge"/>
<validator id="SketchPlugin_NotFixed"/>
</sketch_shape_selector>
<validator id="PartSet_RigidSelection"/>
<validator id="PartSet_ParallelSelection"/>
</feature>
- <!-- SketchConstraintPerpendicular -->
+ <!-- SketchConstraintPerpendicular -->
<feature id="SketchConstraintPerpendicular" title="Perpendicular"
- tooltip="Create constraint defining two perpendicular lines"
+ tooltip="Create constraint defining two orthogonal objects"
icon="icons/Sketch/perpendicular.png"
helpfile="perpendicularFeature.html">
<sketch_shape_selector id="ConstraintEntityA"
- label="First line" tooltip="Select a line"
+ label="First object" tooltip="Select line or arc"
shape_types="edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
- <validator id="GeomValidators_ShapeType" parameters="line"/>
+ <validator id="SketchPlugin_PerpendicularAttr" parameters="ConstraintEntityB"/>
+ <validator id="GeomValidators_ShapeType" parameters="edge"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB"
- label="Second line" tooltip="Select a line"
+ label="Second object" tooltip="Select line or arc"
shape_types="edge">
- <validator id="PartSet_DifferentObjects"/>
+ <validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
- <validator id="GeomValidators_ShapeType" parameters="line"/>
+ <validator id="SketchPlugin_PerpendicularAttr" parameters="ConstraintEntityA"/>
+ <validator id="GeomValidators_ShapeType" parameters="edge"/>
</sketch_shape_selector>
<validator id="PartSet_PerpendicularSelection"/>
</feature>
</sketch_shape_selector>
<validator id="PartSet_CoincidentSelection"/>
</feature>
+ <!-- SketchConstraintCoincidenceInternal -->
+ <feature id="SketchConstraintCoincidenceInternal" title="Internal Coincidence" tooltip="Internal coincidence" icon="icons/Sketch/coincedence.png"
+ helpfile="coincedenceFeature.html" internal="1">
+ <sketch_shape_selector id="ConstraintEntityA" label="First object" tooltip="Select a first object" shape_types="vertex">
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
+ </sketch_shape_selector>
+ <sketch_shape_selector id="ConstraintEntityB" label="Second object" tooltip="Select a second object" shape_types="vertex">
+ <validator id="PartSet_DifferentObjects"/>
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
+ <validator id="SketchPlugin_CoincidenceAttr" parameters="ConstraintEntityA"/>
+ </sketch_shape_selector>
+ <validator id="PartSet_CoincidentSelection"/>
+ </feature>
<!-- SketchConstraintMiddle -->
<feature id="SketchConstraintMiddle" title="Middle point" tooltip="Create constraint for setting middle point on a line"
<!-- SketchConstraintEqual -->
<feature id="SketchConstraintEqual" title="Equal"
- tooltip="Create constraint defining equal lengths of two lines or line and arc or equal radii of two arcs or two circles or arc and circle"
+ tooltip="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"
icon="icons/Sketch/equal.png"
helpfile="equalFeature.html">
<sketch_shape_selector id="ConstraintEntityA"
- label="First object" tooltip="Select line, circle or arc" shape_types="edge">
+ label="First object" tooltip="Select edge" shape_types="edge">
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB"
- label="Second object" tooltip="Select line, circle or arc" shape_types="edge">
+ label="Second object" tooltip="Select edge" shape_types="edge">
<validator id="SketchPlugin_EqualAttr" parameters="ConstraintEntityA"/>
<validator id="PartSet_DifferentObjects"/>
<validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
<validator id="PartSet_EqualSelection"/>
</feature>
- <!-- SketchConstraintCollinear -->
+ <!-- SketchConstraintCollinear -->
<feature id="SketchConstraintCollinear" title="Collinear" tooltip="Create constraint defining collinearity of two lines"
icon="icons/Sketch/collinear.png"
helpfile="collinearFeature.html">
SketchSolver_ConstraintMiddle.h
SketchSolver_ConstraintMirror.h
SketchSolver_ConstraintFixed.h
+ SketchSolver_ConstraintPerpendicular.h
SketchSolver_ConstraintTangent.h
SketchSolver_ConstraintMulti.h
SketchSolver_ConstraintMultiRotation.h
SketchSolver_ConstraintMiddle.cpp
SketchSolver_ConstraintMirror.cpp
SketchSolver_ConstraintFixed.cpp
+ SketchSolver_ConstraintPerpendicular.cpp
SketchSolver_ConstraintTangent.cpp
SketchSolver_ConstraintMulti.cpp
SketchSolver_ConstraintMultiRotation.cpp
SET(SKETCHSOLVER_TEXT_RESOURCES
SketchSolver_msg_en.ts
+ SketchSolver_msg_fr.ts
)
INCLUDE_DIRECTORIES(
PlaneGCSSolver_Storage.h
PlaneGCSSolver_ConstraintWrapper.h
PlaneGCSSolver_EdgeWrapper.h
- PlaneGCSSolver_EdgeWrapper.h
+ PlaneGCSSolver_EntityWrapper.h
PlaneGCSSolver_PointWrapper.h
PlaneGCSSolver_ScalarWrapper.h
PlaneGCSSolver_AngleWrapper.h
+ PlaneGCSSolver_BooleanWrapper.h
PlaneGCSSolver_Tools.h
)
PlaneGCSSolver_PointWrapper.cpp
PlaneGCSSolver_ScalarWrapper.cpp
PlaneGCSSolver_AngleWrapper.cpp
+ PlaneGCSSolver_BooleanWrapper.cpp
PlaneGCSSolver_Tools.cpp
)
#include <PlaneGCSSolver_AttributeBuilder.h>
#include <PlaneGCSSolver_PointWrapper.h>
#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
return theStorage ? theStorage->createParameter() : (new double(0));
}
+static EntityWrapperPtr createBoolean(const AttributePtr& theAttribute)
+{
+ BooleanWrapperPtr aWrapper;
+ AttributeBooleanPtr aBoolean =
+ std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
+ if (aBoolean)
+ aWrapper = BooleanWrapperPtr(new PlaneGCSSolver_BooleanWrapper(aBoolean->value()));
+ return aWrapper;
+}
+
static EntityWrapperPtr createScalar(const AttributePtr& theAttribute,
PlaneGCSSolver_Storage* theStorage)
{
aResult = createPoint(theAttribute, myStorage);
if (!aResult)
aResult = createScalar(theAttribute, myStorage);
+ if (!aResult)
+ aResult = createBoolean(theAttribute);
if (aResult && !myStorage)
aResult->setExternal(true);
return aResult;
--- /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 <PlaneGCSSolver_BooleanWrapper.h>
+
+PlaneGCSSolver_BooleanWrapper::PlaneGCSSolver_BooleanWrapper(bool theParam)
+ : myValue(theParam)
+{
+}
--- /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 PlaneGCSSolver_BooleanWrapper_H_
+#define PlaneGCSSolver_BooleanWrapper_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+
+/**
+ * Wrapper providing storage for boolean values.
+ */
+class PlaneGCSSolver_BooleanWrapper : public PlaneGCSSolver_EntityWrapper
+{
+public:
+ PlaneGCSSolver_BooleanWrapper(bool theValue);
+
+ /// \brief Change value of parameter
+ void setValue(bool theValue)
+ { myValue = theValue; }
+ /// \brief Return value of parameter
+ bool value() const
+ { return myValue; }
+
+ /// \brief Return type of current entity
+ virtual SketchSolver_EntityType type() const
+ { return ENTITY_BOOLEAN; }
+
+protected:
+ bool myValue;
+};
+
+typedef std::shared_ptr<PlaneGCSSolver_BooleanWrapper> BooleanWrapperPtr;
+
+#endif
// Predefined values for identifiers
const ConstraintID CID_UNKNOWN = 0;
const ConstraintID CID_MOVEMENT = -1;
-const ConstraintID CID_FICTIVE = 1024;
+const ConstraintID CID_FICTIVE = 99;
/// Types of entities
enum SketchSolver_EntityType {
ENTITY_UNKNOWN = 0,
+ ENTITY_BOOLEAN,
ENTITY_SCALAR,
ENTITY_ANGLE,
ENTITY_POINT,
ENTITY_LINE,
ENTITY_CIRCLE,
- ENTITY_ARC
+ ENTITY_ARC,
+ ENTITY_ELLIPSE,
+ ENTITY_ELLIPTIC_ARC
};
/// Types of constraints
CONSTRAINT_UNKNOWN = 0,
CONSTRAINT_COINCIDENCE, // base coincidence if we don't know exact type yet
CONSTRAINT_PT_PT_COINCIDENT,
- CONSTRAINT_PT_ON_LINE,
- CONSTRAINT_PT_ON_CIRCLE,
+ CONSTRAINT_PT_ON_CURVE,
CONSTRAINT_MIDDLE_POINT,
CONSTRAINT_DISTANCE, // base distance if we don't know the measured objects yet
CONSTRAINT_PT_PT_DISTANCE,
CONSTRAINT_VERTICAL,
CONSTRAINT_PARALLEL,
CONSTRAINT_PERPENDICULAR,
+ CONSTRAINT_PERPENDICULAR_CURVES,
CONSTRAINT_SYMMETRIC,
CONSTRAINT_EQUAL, // base equality if we don't know the measured objects yet
CONSTRAINT_EQUAL_LINES,
CONSTRAINT_EQUAL_LINE_ARC,
CONSTRAINT_EQUAL_RADIUS,
+ CONSTRAINT_EQUAL_ELLIPSES,
CONSTRAINT_TANGENT, // base tangency if we don't know the measured objects yet
CONSTRAINT_TANGENT_CIRCLE_LINE,
- CONSTRAINT_TANGENT_CIRCLE_CIRCLE,
+ CONSTRAINT_TANGENT_CURVE_CURVE,
CONSTRAINT_COLLINEAR,
CONSTRAINT_MULTI_TRANSLATION,
CONSTRAINT_MULTI_ROTATION
#include <PlaneGCSSolver_EdgeWrapper.h>
#include <cmath>
+static bool isLine(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Line>(theEntity).get();
+}
+
+static bool isCircle(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Circle>(theEntity).get();
+}
+
+static bool isArc(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Arc>(theEntity).get();
+}
+
+static bool isEllipse(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::Ellipse>(theEntity).get();
+}
+
+static bool isEllipticArc(const GCSCurvePtr& theEntity)
+{
+ return std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEntity).get();
+}
+
+
PlaneGCSSolver_EdgeWrapper::PlaneGCSSolver_EdgeWrapper(const GCSCurvePtr theEntity)
: myEntity(theEntity)
{
- std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
- if (aLine) myType = ENTITY_LINE;
- else {
- std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(myEntity);
- if (anArc) myType = ENTITY_ARC;
- else {
- std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
- if (aCircle) myType = ENTITY_CIRCLE;
- }
- }
+ if (isLine(myEntity))
+ myType = ENTITY_LINE;
+ else if (isArc(myEntity))
+ myType = ENTITY_ARC;
+ else if (isCircle(myEntity))
+ myType = ENTITY_CIRCLE;
+ else if (isEllipticArc(myEntity))
+ myType = ENTITY_ELLIPTIC_ARC;
+ else if (isEllipse(myEntity))
+ myType = ENTITY_ELLIPSE;
}
static double squareDistance(const GCS::Point& theP1, const GCS::Point& theP2)
bool PlaneGCSSolver_EdgeWrapper::isDegenerated() const
{
- static const double aSqTol = tolerance * 1e-2;
- static const double aMaxRadius = 1e8;
+ static const double THE_SQ_TOL = tolerance * 1e-2;
+ static const double THE_ANGLE_TOL = 1.e-5;
+ static const double THE_MAX_RADIUS = 1e8;
+ static const double THE_SQ_MAX_RADIUS = THE_MAX_RADIUS * THE_MAX_RADIUS;
+
if (myType == ENTITY_LINE) {
std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
- return squareDistance(aLine->p1, aLine->p2) < aSqTol;
+ return squareDistance(aLine->p1, aLine->p2) < THE_SQ_TOL;
}
else if (myType == ENTITY_CIRCLE) {
std::shared_ptr<GCS::Circle> aCircle = std::dynamic_pointer_cast<GCS::Circle>(myEntity);
- return *aCircle->rad < tolerance || *aCircle->rad > aMaxRadius;
+ return *aCircle->rad < tolerance || *aCircle->rad > THE_MAX_RADIUS;
}
else if (myType == ENTITY_ARC) {
- static const double anAngleTol = 1.e-5;
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(myEntity);
double anAngleDiff = fabs(*anArc->startAngle - *anArc->endAngle);
double aSqRadius = squareDistance(anArc->center, anArc->start);
- return aSqRadius < aSqTol || aSqRadius > aMaxRadius * aMaxRadius || // <- arc radius
- anAngleDiff < anAngleTol || fabs(anAngleDiff - 2*PI) < anAngleTol; // <- arc angle
+ return aSqRadius < THE_SQ_TOL || aSqRadius > THE_SQ_MAX_RADIUS || // <- arc radius
+ anAngleDiff < THE_ANGLE_TOL || fabs(anAngleDiff - 2*PI) < THE_ANGLE_TOL; // <- arc angle
+ }
+ else if (myType == ENTITY_ELLIPSE) {
+ std::shared_ptr<GCS::Ellipse> anEllipse = std::dynamic_pointer_cast<GCS::Ellipse>(myEntity);
+ return *anEllipse->radmin < tolerance || anEllipse->getRadMaj() > THE_MAX_RADIUS;
+ }
+ else if (myType == ENTITY_ELLIPTIC_ARC) {
+ std::shared_ptr<GCS::ArcOfEllipse> anArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(myEntity);
+ double anAngleDiff = fabs(*anArc->startAngle - *anArc->endAngle);
+ return *anArc->radmin < THE_SQ_TOL || anArc->getRadMaj() > THE_SQ_MAX_RADIUS || // <- arc radius
+ anAngleDiff < THE_ANGLE_TOL || fabs(anAngleDiff - 2*PI) < THE_ANGLE_TOL; // <- arc angle
}
return false;
}
#define PlaneGCSSolver_EdgeWrapper_H_
#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
#include <PlaneGCSSolver_EntityWrapper.h>
/**
bool isDegenerated() const;
+ void setReversed(BooleanWrapperPtr theReversed)
+ { myReversed = theReversed; }
+
+ bool isReversed() const
+ { return myReversed ? myReversed->value() : false; }
+
private:
SketchSolver_EntityType myType;
GCSCurvePtr myEntity;
+ BooleanWrapperPtr myReversed; // preferably used to control arc orientation
};
typedef std::shared_ptr<PlaneGCSSolver_EdgeWrapper> EdgeWrapperPtr;
#include <list>
#include <memory>
+class PlaneGCSSolver_EntityWrapper;
+typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
+
/**
* Wrapper providing operations with entities regardless the solver.
*/
/// \brief Return the External flag
bool isExternal() const { return myExternal; }
+ /// \brief Store names of attributes and their values if necessary
+ void setAdditionalAttributes(const std::map<std::string, EntityWrapperPtr>& theAttribues)
+ { myAdditionalAttributes = theAttribues; }
+ /// \brief Return the list of additional attributes
+ const std::map<std::string, EntityWrapperPtr>& additionalAttributes() const
+ { return myAdditionalAttributes; }
+
private:
bool myExternal;
+ std::map<std::string, EntityWrapperPtr> myAdditionalAttributes;
};
-typedef std::shared_ptr<PlaneGCSSolver_EntityWrapper> EntityWrapperPtr;
-
#endif
#include <PlaneGCSSolver_EdgeWrapper.h>
#include <PlaneGCSSolver_PointWrapper.h>
#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
+#include <PlaneGCSSolver_Tools.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_IntersectionPoint.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
PlaneGCSSolver_Storage* theStorage);
+static EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+ PlaneGCSSolver_Storage* theStorage);
PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
// Arc
else if (aFeatureKind == SketchPlugin_Arc::ID())
aResult = createArc(myAttributes, myStorage);
+ // Ellipse
+ else if (aFeatureKind == SketchPlugin_Ellipse::ID())
+ aResult = createEllipse(myAttributes);
+ // Arc of ellipse
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+ aResult = createEllipticArc(myAttributes, myStorage);
// Point (it has low probability to be an attribute of constraint, so it is checked at the end)
else if (aFeatureKind == SketchPlugin_Point::ID() ||
aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
PlaneGCSSolver_Storage* theStorage)
{
std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
+ BooleanWrapperPtr isReversed;
// Base attributes of arc (center, start and end points)
AttributeEntityMap::const_iterator anIt = theAttributes.begin();
for (; anIt != theAttributes.end(); ++anIt) {
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
- if (!aPoint)
- continue;
-
- if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
- aNewArc->center = *(aPoint->point());
- else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
- aNewArc->start = *(aPoint->point());
- else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
- aNewArc->end = *(aPoint->point());
+ if (aPoint) {
+ if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
+ aNewArc->center = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
+ aNewArc->start = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
+ aNewArc->end = *(aPoint->point());
+ }
+ else {
+ // reversed flag
+ isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
+ }
}
- // Additional atrtributes of arc necessary for PlaneGCS solver
+ // Additional attributes of arc necessary for PlaneGCS solver
// (start and end angles, radius)
aNewArc->startAngle = createParameter(theStorage);
aNewArc->endAngle = createParameter(theStorage);
aNewArc->rad = createParameter(theStorage);
- static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
- std::shared_ptr<GeomAPI_Pnt2d> aCenter(
- new GeomAPI_Pnt2d(*aNewArc->center.x, *aNewArc->center.y));
- std::shared_ptr<GeomAPI_Pnt2d> aStart(
- new GeomAPI_Pnt2d(*aNewArc->start.x, *aNewArc->start.y));
+ EdgeWrapperPtr anArcWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+ anArcWrapper->setReversed(isReversed);
+ PlaneGCSSolver_Tools::recalculateArcParameters(anArcWrapper);
- *aNewArc->rad = aStart->distance(aCenter);
+ return anArcWrapper;
+}
- std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
- *aNewArc->startAngle = OX->angle(aDir);
+EntityWrapperPtr createEllipse(const AttributeEntityMap& theAttributes)
+{
+ std::shared_ptr<GCS::Ellipse> aNewEllipse(new GCS::Ellipse);
- aDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
- *aNewArc->endAngle = OX->angle(aDir);
+ std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
- return EntityWrapperPtr(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (aPoint) {
+ if (anIt->first->id() == SketchPlugin_Ellipse::CENTER_ID())
+ aNewEllipse->center = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Ellipse::FIRST_FOCUS_ID())
+ aNewEllipse->focus1 = *(aPoint->point());
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+ else if (anIt->first->id() == SketchPlugin_Ellipse::MINOR_RADIUS_ID()) {
+ ScalarWrapperPtr aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ aNewEllipse->radmin = aScalar->scalar();
+ }
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+
+ EntityWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewEllipse));
+ anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+ return anEllipseWrapper;
+}
+
+EntityWrapperPtr createEllipticArc(const AttributeEntityMap& theAttributes,
+ PlaneGCSSolver_Storage* theStorage)
+{
+ std::shared_ptr<GCS::ArcOfEllipse> aNewArc(new GCS::ArcOfEllipse);
+
+ BooleanWrapperPtr isReversed;
+ std::map<std::string, EntityWrapperPtr> anAdditionalAttributes;
+
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (aPoint) {
+ if (anIt->first->id() == SketchPlugin_EllipticArc::CENTER_ID())
+ aNewArc->center = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::FIRST_FOCUS_ID())
+ aNewArc->focus1 = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::START_POINT_ID())
+ aNewArc->start = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::END_POINT_ID())
+ aNewArc->end = *(aPoint->point());
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::MINOR_RADIUS_ID()) {
+ ScalarWrapperPtr aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ aNewArc->radmin = aScalar->scalar();
+ }
+ else if (anIt->first->id() == SketchPlugin_EllipticArc::REVERSED_ID())
+ isReversed = std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(anIt->second);
+ else
+ anAdditionalAttributes[anIt->first->id()] = anIt->second;
+ }
+
+ // Additional attributes of elliptic arc necessary for PlaneGCS solver (start and end angles)
+ aNewArc->startAngle = createParameter(theStorage);
+ aNewArc->endAngle = createParameter(theStorage);
+
+ EdgeWrapperPtr anEllipseWrapper(new PlaneGCSSolver_EdgeWrapper(aNewArc));
+ anEllipseWrapper->setReversed(isReversed);
+ anEllipseWrapper->setAdditionalAttributes(anAdditionalAttributes);
+ PlaneGCSSolver_Tools::recalculateArcParameters(anEllipseWrapper);
+
+ return anEllipseWrapper;
}
bool isAttributeApplicable(const std::string& theAttrName, const std::string& theOwnerName)
if (theOwnerName == SketchPlugin_Arc::ID()) {
return theAttrName == SketchPlugin_Arc::CENTER_ID() ||
theAttrName == SketchPlugin_Arc::START_ID() ||
- theAttrName == SketchPlugin_Arc::END_ID();
+ theAttrName == SketchPlugin_Arc::END_ID() ||
+ theAttrName == SketchPlugin_Arc::REVERSED_ID();
}
else if (theOwnerName == SketchPlugin_Circle::ID()) {
return theAttrName == SketchPlugin_Circle::CENTER_ID() ||
return theAttrName == SketchPlugin_Line::START_ID() ||
theAttrName == SketchPlugin_Line::END_ID();
}
+ else if (theOwnerName == SketchPlugin_Ellipse::ID()) {
+ return theAttrName == SketchPlugin_Ellipse::CENTER_ID() ||
+ theAttrName == SketchPlugin_Ellipse::FIRST_FOCUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::SECOND_FOCUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MAJOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_Ellipse::MINOR_RADIUS_ID();
+ }
+ else if (theOwnerName == SketchPlugin_EllipticArc::ID()) {
+ return theAttrName == SketchPlugin_EllipticArc::CENTER_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::FIRST_FOCUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::SECOND_FOCUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_START_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MINOR_AXIS_END_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MAJOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::MINOR_RADIUS_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::START_POINT_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::END_POINT_ID() ||
+ theAttrName == SketchPlugin_EllipticArc::REVERSED_ID();
+ }
// suppose that all remaining features are points
return theAttrName == SketchPlugin_Point::COORD_ID();
#include <Events_LongOp.h>
// Multiplier to correlate IDs of SketchPlugin constraint and primitive PlaneGCS constraints
-static const int THE_CONSTRAINT_MULT = 10;
+static const int THE_CONSTRAINT_MULT = 100;
PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
void PlaneGCSSolver_Solver::addFictiveConstraintIfNecessary()
{
- if (!myConstraints.empty() &&
- myConstraints.find(CID_MOVEMENT) == myConstraints.end())
- return;
+ bool hasOnlyMovement = true;
+ for (ConstraintMap::iterator anIt = myConstraints.begin();
+ anIt != myConstraints.end() && hasOnlyMovement; ++anIt)
+ hasOnlyMovement = anIt->first == CID_MOVEMENT;
+ if (!hasOnlyMovement)
+ return; // regular constraints are available too
if (myFictiveConstraint)
return; // no need several fictive constraints
void PlaneGCSSolver_Solver::removeFictiveConstraint()
{
if (myFictiveConstraint) {
- myEquationSystem->removeConstraint(myFictiveConstraint);
+ myEquationSystem->clearByTag(myFictiveConstraint->getTag());
myParameters.pop_back();
GCS::VEC_pD aParams = myFictiveConstraint->params();
- for (GCS::VEC_pD::iterator anIt = aParams.begin(); anIt != aParams.end(); ++ anIt)
- delete *anIt;
+ for (GCS::VEC_pD::iterator anIt = aParams.begin(); anIt != aParams.end(); ++anIt) {
+ double* aPar = *anIt;
+ delete aPar;
+ }
delete myFictiveConstraint;
myFictiveConstraint = 0;
}
#include <PlaneGCSSolver_Storage.h>
#include <PlaneGCSSolver_Solver.h>
+#include <PlaneGCSSolver_BooleanWrapper.h>
#include <PlaneGCSSolver_ConstraintWrapper.h>
#include <PlaneGCSSolver_EdgeWrapper.h>
#include <PlaneGCSSolver_PointWrapper.h>
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Ellipse.h>
#include <SketchPlugin_Projection.h>
#include <cmath>
/// \brief Update value
static bool updateValue(const double& theSource, double& theDest)
{
- static const double aTol = 1000. * tolerance;
+ static const double aTol = 1.e4 * tolerance;
bool isUpdated = fabs(theSource - theDest) > aTol;
if (isUpdated)
theDest = theSource;
isUpdated = updateValue(aScalar->value(), aValue);
if (isUpdated)
aWrapper->setValue(aValue);
+ } else {
+ AttributeBooleanPtr aBoolean =
+ std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(theAttribute);
+ if (aBoolean) {
+ BooleanWrapperPtr aWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_BooleanWrapper>(theEntity);
+ isUpdated = aWrapper->value() != aBoolean->value();
+ aWrapper->setValue(aBoolean->value());
+ }
}
}
// (do not want to add several copies of it while adding attributes)
aRelated = createFeature(theFeature, &aBuilder);
myFeatureMap[theFeature] = aRelated;
- createArcConstraints(aRelated);
+ createAuxiliaryConstraints(aRelated);
isUpdated = true;
}
std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
for (; anAttrIt != anAttributes.end(); ++anAttrIt)
if ((*anAttrIt)->attributeType() == GeomDataAPI_Point2D::typeId() ||
- (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId())
+ (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId() ||
+ (*anAttrIt)->attributeType() == ModelAPI_AttributeBoolean::typeId())
isUpdated = update(*anAttrIt) || isUpdated;
// check external attribute is changed
notify(theFeature);
// update arc
- if (aRelated && aRelated->type() == ENTITY_ARC) {
- /// TODO: this code should be shared with FeatureBuilder somehow
-
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
- std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(aRelated);
- std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
-
- static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
- std::shared_ptr<GeomAPI_Pnt2d> aCenter(
- new GeomAPI_Pnt2d(*anArc->center.x, *anArc->center.y));
- std::shared_ptr<GeomAPI_Pnt2d> aStart(
- new GeomAPI_Pnt2d(*anArc->start.x, *anArc->start.y));
-
- *anArc->rad = aStart->distance(aCenter);
-
- std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
- *anArc->startAngle = OX->angle(aDir);
-
- aDir = std::shared_ptr<GeomAPI_Dir2d>(
- new GeomAPI_Dir2d((*anArc->end.x) - aCenter->x(), (*anArc->end.y) - aCenter->y()));
- *anArc->endAngle = OX->angle(aDir);
- }
+ if (aRelated)
+ PlaneGCSSolver_Tools::recalculateArcParameters(aRelated);
return isUpdated;
}
if (theEntity->isExternal())
return;
- removeArcConstraints(theEntity);
+ removeAuxiliaryConstraints(theEntity);
GCS::SET_pD aParameters = PlaneGCSSolver_Tools::parameters(theEntity);
mySketchSolver->removeParameters(aParameters);
mySketchSolver->addParameters(aParameters);
theEntity->setExternal(false);
- createArcConstraints(theEntity);
+ createAuxiliaryConstraints(theEntity);
myNeedToResolve = true;
}
-void PlaneGCSSolver_Storage::createArcConstraints(const EntityWrapperPtr& theArc)
+static void createArcConstraints(const EntityWrapperPtr& theArc,
+ const SolverPtr& theSolver,
+ const ConstraintID theConstraintID,
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
{
- if (!theArc || theArc->type() != ENTITY_ARC || theArc->isExternal())
- return;
-
EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
anArc->center, anArc->end, anArc->endAngle)));
ConstraintWrapperPtr aWrapper(
- new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
- aWrapper->setId(++myConstraintLastID);
- constraintsToSolver(aWrapper, mySketchSolver);
+ new PlaneGCSSolver_ConstraintWrapper(anArcConstraints, CONSTRAINT_UNKNOWN));
+ aWrapper->setId(theConstraintID);
+ constraintsToSolver(aWrapper, theSolver);
+
+ theConstraints[theArc] = aWrapper;
+}
+
+static void createEllipseConstraints(
+ const EntityWrapperPtr& theEllipse,
+ const SolverPtr& theSolver,
+ const ConstraintID theConstraintID,
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
+{
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipse);
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
+
+ // Additional constaints to fix ellipse's extra points
+ std::list<GCSConstraintPtr> anEllipseConstraints;
+
+ const std::map<std::string, EntityWrapperPtr>& anAttributes = theEllipse->additionalAttributes();
+ for (std::map<std::string, EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
+ anIt != anAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (!aPoint)
+ continue;
+
+ GCS::InternalAlignmentType anAlignmentX, anAlignmentY;
+ if (anIt->first == SketchPlugin_Ellipse::SECOND_FOCUS_ID())
+ anAlignmentX = GCS::EllipseFocus2X;
+ else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID())
+ anAlignmentX = GCS::EllipseNegativeMajorX;
+ else if (anIt->first == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())
+ anAlignmentX = GCS::EllipsePositiveMajorX;
+ else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_START_ID())
+ anAlignmentX = GCS::EllipseNegativeMinorX;
+ else if (anIt->first == SketchPlugin_Ellipse::MINOR_AXIS_END_ID())
+ anAlignmentX = GCS::EllipsePositiveMinorX;
+
+ anEllipseConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintInternalAlignmentPoint2Ellipse(
+ *anEllipse, *(aPoint->point()), anAlignmentX)));
+ anAlignmentY = (GCS::InternalAlignmentType)((int)anAlignmentX + 1);
+ anEllipseConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintInternalAlignmentPoint2Ellipse(
+ *anEllipse, *(aPoint->point()), anAlignmentY)));
+ }
+
+ // constraint to bind the major radius value
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aMajorAxisStart =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
+ anAttributes.at(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()));
+ ScalarWrapperPtr aMajorRadius =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(
+ anAttributes.at(SketchPlugin_Ellipse::MAJOR_RADIUS_ID()));
+ anEllipseConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ anEllipse->center, *(aMajorAxisStart->point()), aMajorRadius->scalar())));
+
+ ConstraintWrapperPtr aWrapper(
+ new PlaneGCSSolver_ConstraintWrapper(anEllipseConstraints, CONSTRAINT_UNKNOWN));
+ aWrapper->setId(theConstraintID);
+ if (theSolver)
+ constraintsToSolver(aWrapper, theSolver);
+
+ theConstraints[theEllipse] = aWrapper;
+}
+
+static void createEllipticArcConstraints(
+ const EntityWrapperPtr& theEllipticArc,
+ const SolverPtr& theSolver,
+ const ConstraintID theConstraintID,
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>& theConstraints)
+{
+ // create base constraints for the ellipse without adding them to solver
+ createEllipseConstraints(theEllipticArc, SolverPtr(), theConstraintID, theConstraints);
+
+ ConstraintWrapperPtr& aConstraint = theConstraints[theEllipticArc];
+ std::list<GCSConstraintPtr> anEllArcConstraints = aConstraint->constraints();
+
+ // constrain extremities of the elliptic arc
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEllipticArc);
+ std::shared_ptr<GCS::ArcOfEllipse> anArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
+
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->start, anArc->start.x, *anArc, anArc->startAngle)));
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->start, anArc->start.y, *anArc, anArc->startAngle)));
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->end, anArc->end.x, *anArc, anArc->endAngle)));
+ anEllArcConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(anArc->end, anArc->end.y, *anArc, anArc->endAngle)));
+
+ aConstraint->setConstraints(anEllArcConstraints);
+ constraintsToSolver(aConstraint, theSolver);
+}
+
+void PlaneGCSSolver_Storage::createAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
+{
+ if (!theEntity || theEntity->isExternal())
+ return;
- myArcConstraintMap[theArc] = aWrapper;
+ if (theEntity->type() == ENTITY_ARC)
+ createArcConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+ else if (theEntity->type() == ENTITY_ELLIPSE)
+ createEllipseConstraints(theEntity, mySketchSolver, ++myConstraintLastID, myAuxConstraintMap);
+ else if (theEntity->type() == ENTITY_ELLIPTIC_ARC) {
+ createEllipticArcConstraints(theEntity, mySketchSolver,
+ ++myConstraintLastID, myAuxConstraintMap);
+ }
}
-void PlaneGCSSolver_Storage::removeArcConstraints(const EntityWrapperPtr& theArc)
+void PlaneGCSSolver_Storage::removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity)
{
std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
- aFound = myArcConstraintMap.find(theArc);
- if (aFound != myArcConstraintMap.end()) {
+ aFound = myAuxConstraintMap.find(theEntity);
+ if (aFound != myAuxConstraintMap.end()) {
mySketchSolver->removeConstraint(aFound->second->id());
- myArcConstraintMap.erase(aFound);
+ myAuxConstraintMap.erase(aFound);
+ }
+}
+
+template <typename ARCTYPE>
+void adjustArcParametrization(ARCTYPE& theArc, bool theReversed)
+{
+ // tune start angle of the arc to be in [0, 2PI]
+ while (*theArc.startAngle < -PI)
+ *theArc.startAngle += 2.0 * PI;
+ while (*theArc.startAngle >= PI)
+ *theArc.startAngle -= 2.0 * PI;
+ // adjust end angle of the arc
+ if (theReversed) {
+ while (*theArc.endAngle > *theArc.startAngle)
+ *theArc.endAngle -= 2.0 * PI;
+ while (*theArc.endAngle + 2 * PI < *theArc.startAngle)
+ *theArc.endAngle += 2.0 * PI;
+ }
+ else {
+ while (*theArc.endAngle < *theArc.startAngle)
+ *theArc.endAngle += 2.0 * PI;
+ while (*theArc.endAngle > *theArc.startAngle + 2 * PI)
+ *theArc.endAngle -= 2.0 * PI;
+ }
+}
+
+void PlaneGCSSolver_Storage::adjustParametrizationOfArcs()
+{
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator anIt = myAuxConstraintMap.begin();
+ for (; anIt != myAuxConstraintMap.end(); ++anIt) {
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anIt->first);
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
+ if (anArc)
+ adjustArcParametrization(*anArc, anEdge->isReversed());
+ else {
+ std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
+ if (aEllArc)
+ adjustArcParametrization(*aEllArc, anEdge->isReversed());
+ }
}
+
+ // update parameters of Middle point constraint for point on arc
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator aCIt = myConstraintMap.begin();
+ for (; aCIt != myConstraintMap.end(); ++aCIt)
+ if (aCIt->second->type() == CONSTRAINT_MIDDLE_POINT) {
+ notify(aCIt->first);
+ }
}
aDestroyer.remove(aFIter->second);
// remove invalid arc
- removeArcConstraints(aFIter->second);
+ removeAuxiliaryConstraints(aFIter->second);
}
std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
/// \brief Check the storage has constraints
virtual bool isEmpty() const
- { return SketchSolver_Storage::isEmpty() && myArcConstraintMap.empty(); }
+ { return SketchSolver_Storage::isEmpty() && myAuxConstraintMap.empty(); }
+
+ /// \brief Make parametrization of arcs consistent.
+ /// Forward arcs should have the last parameter greater than the first parameter.
+ /// Reversed arcs should have the last parameter lesser than the first parameter.
+ virtual void adjustParametrizationOfArcs();
private:
/// \brief Convert feature using specified builder.
EntityWrapperPtr createAttribute(const AttributePtr& theAttribute,
PlaneGCSSolver_EntityBuilder* theBuilder);
- void createArcConstraints(const EntityWrapperPtr& theArc);
- void removeArcConstraints(const EntityWrapperPtr& theArc);
+ /// \brief Create additional constaints:
+ /// * for arc to fix extra parameters;
+ /// * for ellipse to keep auxiliary points on their places
+ void createAuxiliaryConstraints(const EntityWrapperPtr& theEntity);
+ void removeAuxiliaryConstraints(const EntityWrapperPtr& theEntity);
private:
ConstraintID myConstraintLastID; ///< identifier of last added constraint
- /// additional constraints for correct processing of the arcs
- std::map<EntityWrapperPtr, ConstraintWrapperPtr> myArcConstraintMap;
+ /// additional constraints for correct processing of the arcs, ellipses, elliptic arcs
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr> myAuxConstraintMap;
/// list of removed constraints to notify solver
std::list<GCSConstraintPtr> myRemovedConstraints;
#include <SketchSolver_Constraint.h>
#include <SketchSolver_ConstraintAngle.h>
#include <SketchSolver_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchSolver_ConstraintCollinear.h>
#include <SketchSolver_ConstraintDistance.h>
#include <SketchSolver_ConstraintEqual.h>
#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_ConstraintMiddle.h>
#include <SketchSolver_ConstraintMirror.h>
+#include <SketchSolver_ConstraintPerpendicular.h>
#include <SketchSolver_ConstraintTangent.h>
#include <SketchSolver_ConstraintMultiRotation.h>
#include <SketchSolver_ConstraintMultiTranslation.h>
#include <SketchPlugin_ConstraintMiddle.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintRigid.h>
+#include <SketchPlugin_ConstraintPerpendicular.h>
#include <SketchPlugin_ConstraintTangent.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
+#include <GeomAPI_Circ2d.h>
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Ellipse2d.h>
+#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt2d.h>
+
#include <cmath>
createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintPointsCollinear(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint3);
static ConstraintWrapperPtr
createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed);
static ConstraintWrapperPtr
createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters);
+static ConstraintWrapperPtr
+ createConstraintAngleBetweenCurves(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2);
static GCS::SET_pD scalarParameters(const ScalarWrapperPtr& theScalar);
static GCS::SET_pD pointParameters(const PointWrapperPtr& thePoint);
static GCS::SET_pD lineParameters(const EdgeWrapperPtr& theLine);
static GCS::SET_pD circleParameters(const EdgeWrapperPtr& theCircle);
static GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc);
+static GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse);
+static GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc);
+
+static double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2);
SolverConstraintPtr PlaneGCSSolver_Tools::createConstraint(ConstraintPtr theConstraint)
{
- if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+ theConstraint->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintCoincidence(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintCollinear(theConstraint));
return SolverConstraintPtr(new SketchSolver_ConstraintMultiRotation(theConstraint));
} else if (theConstraint->getKind() == SketchPlugin_ConstraintAngle::ID()) {
return SolverConstraintPtr(new SketchSolver_ConstraintAngle(theConstraint));
+ } else if (theConstraint->getKind() == SketchPlugin_ConstraintPerpendicular::ID()) {
+ return SolverConstraintPtr(new SketchSolver_ConstraintPerpendicular(theConstraint));
}
// All other types of constraints
return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity1 = GCS_EDGE_WRAPPER(theEntity1);
switch (theType) {
case CONSTRAINT_PT_PT_COINCIDENT:
aResult = createConstraintCoincidence(aPoint1, aPoint2);
break;
- case CONSTRAINT_PT_ON_LINE:
- case CONSTRAINT_PT_ON_CIRCLE:
- aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_EDGE_WRAPPER(theEntity1));
+ case CONSTRAINT_PT_ON_CURVE:
+ aResult = anEntity1 ? createConstraintPointOnEntity(theType, aPoint1, anEntity1):
+ createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
break;
case CONSTRAINT_MIDDLE_POINT:
- aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1));
+ aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
break;
case CONSTRAINT_PT_PT_DISTANCE:
aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
case CONSTRAINT_PT_LINE_DISTANCE:
aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
aPoint1,
- GCS_EDGE_WRAPPER(theEntity1));
+ anEntity1);
break;
case CONSTRAINT_HORIZONTAL_DISTANCE:
case CONSTRAINT_VERTICAL_DISTANCE:
aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
break;
case CONSTRAINT_RADIUS:
- aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
- GCS_EDGE_WRAPPER(theEntity1));
+ aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue), anEntity1);
break;
case CONSTRAINT_ANGLE:
aResult = createConstraintAngle(theConstraint,
GCS_SCALAR_WRAPPER(theValue),
- GCS_EDGE_WRAPPER(theEntity1), GCS_EDGE_WRAPPER(theEntity2));
+ anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
case CONSTRAINT_FIXED:
break;
case CONSTRAINT_HORIZONTAL:
case CONSTRAINT_VERTICAL:
- aResult = createConstraintHorizVert(theType, GCS_EDGE_WRAPPER(theEntity1));
+ aResult = createConstraintHorizVert(theType, anEntity1);
break;
case CONSTRAINT_PARALLEL:
- aResult = createConstraintParallel(GCS_EDGE_WRAPPER(theEntity1),
- GCS_EDGE_WRAPPER(theEntity2));
+ aResult = createConstraintParallel(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
case CONSTRAINT_PERPENDICULAR:
- aResult = createConstraintPerpendicular(GCS_EDGE_WRAPPER(theEntity1),
- GCS_EDGE_WRAPPER(theEntity2));
+ aResult = createConstraintPerpendicular(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
+ break;
+ case CONSTRAINT_PERPENDICULAR_CURVES:
+ aResult = createConstraintAngleBetweenCurves(GCS_SCALAR_WRAPPER(theValue),
+ aPoint1, anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
case CONSTRAINT_EQUAL_LINES:
+ case CONSTRAINT_EQUAL_ELLIPSES:
anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
case CONSTRAINT_EQUAL_LINE_ARC:
case CONSTRAINT_EQUAL_RADIUS:
aResult = createConstraintEqual(theType,
- GCS_EDGE_WRAPPER(theEntity1),
+ anEntity1,
GCS_EDGE_WRAPPER(theEntity2),
anIntermediate);
break;
return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
}
+std::shared_ptr<GeomAPI_Circ2d> PlaneGCSSolver_Tools::circle(EntityWrapperPtr theEntity)
+{
+ if (theEntity->type() != ENTITY_CIRCLE && theEntity->type() != ENTITY_ARC)
+ return std::shared_ptr<GeomAPI_Circ2d>();
+
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
+ std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
+ return std::shared_ptr<GeomAPI_Circ2d>(
+ new GeomAPI_Circ2d(*(aCirc->center.x), *(aCirc->center.y), *(aCirc->rad)));
+}
+
+std::shared_ptr<GeomAPI_Ellipse2d> PlaneGCSSolver_Tools::ellipse(EntityWrapperPtr theEntity)
+{
+ if (theEntity->type() != ENTITY_ELLIPSE && theEntity->type() != ENTITY_ELLIPTIC_ARC)
+ return std::shared_ptr<GeomAPI_Ellipse2d>();
+
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity);
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
+
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter(
+ new GeomAPI_Pnt2d(*(anEllipse->center.x), *(anEllipse->center.y)));
+ std::shared_ptr<GeomAPI_Dir2d> anAxis(new GeomAPI_Dir2d(
+ *(anEllipse->focus1.x) - *(anEllipse->center.x),
+ *(anEllipse->focus1.y) - *(anEllipse->center.y)));
+
+ return std::shared_ptr<GeomAPI_Ellipse2d>(
+ new GeomAPI_Ellipse2d(aCenter, anAxis, anEllipse->getRadMaj(), *anEllipse->radmin));
+}
+
+void PlaneGCSSolver_Tools::recalculateArcParameters(EntityWrapperPtr theArc)
+{
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEdge =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theArc);
+ if (!anEdge)
+ return;
+
+ if (anEdge->type() == ENTITY_ARC) {
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEdge->entity());
+
+ GCS::Point aCenter = anArc->center;
+ GCS::Point aStartPnt = anArc->start;
+ GCS::Point aEndPnt = anArc->end;
+
+ *anArc->rad = distance(aCenter, aStartPnt);
+
+ static GeomDir2dPtr OX(new GeomAPI_Dir2d(1.0, 0.0));
+
+ GeomDir2dPtr aDir(new GeomAPI_Dir2d(*aStartPnt.x - *aCenter.x, *aStartPnt.y - *aCenter.y));
+ *anArc->startAngle = OX->angle(aDir);
+
+ aDir.reset(new GeomAPI_Dir2d(*aEndPnt.x - *aCenter.x, *aEndPnt.y - *aCenter.y));
+ *anArc->endAngle = OX->angle(aDir);
+ }
+ else if (anEdge->type() == ENTITY_ELLIPTIC_ARC) {
+ std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEdge->entity());
+
+ GeomPnt2dPtr aCenter(new GeomAPI_Pnt2d(*aEllArc->center.x, *aEllArc->center.y));
+ GeomPnt2dPtr aStartPnt(new GeomAPI_Pnt2d(*aEllArc->start.x, *aEllArc->start.y));
+ GeomPnt2dPtr aEndPnt(new GeomAPI_Pnt2d(*aEllArc->end.x, *aEllArc->end.y));
+
+ GeomDir2dPtr anAxis(new GeomAPI_Dir2d(*aEllArc->focus1.x - aCenter->x(),
+ *aEllArc->focus1.y - aCenter->y()));
+ GeomAPI_Ellipse2d anEllipse(aCenter, anAxis, aEllArc->getRadMaj(), *aEllArc->radmin);
+ anEllipse.parameter(aStartPnt, 1.e-4, *aEllArc->startAngle);
+ anEllipse.parameter(aEndPnt, 1.e-4, *aEllArc->endAngle);
+ }
+}
+
+
GCS::SET_pD PlaneGCSSolver_Tools::parameters(const EntityWrapperPtr& theEntity)
{
return circleParameters(GCS_EDGE_WRAPPER(theEntity));
case ENTITY_ARC:
return arcParameters(GCS_EDGE_WRAPPER(theEntity));
+ case ENTITY_ELLIPSE:
+ return ellipseParameters(GCS_EDGE_WRAPPER(theEntity));
+ case ENTITY_ELLIPTIC_ARC:
+ return ellipticArcParameters(GCS_EDGE_WRAPPER(theEntity));
default: break;
}
return GCS::SET_pD();
new GCS::ConstraintP2PDistance(*(thePoint->point()), aCirc->center, aCirc->rad));
break;
}
+ case ENTITY_ELLIPSE:
+ case ENTITY_ELLIPTIC_ARC: {
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEntity->entity());
+ aNewConstr = GCSConstraintPtr(
+ new GCS::ConstraintPointOnEllipse(*(thePoint->point()), *anEllipse));
+ break;
+ }
default:
return ConstraintWrapperPtr();
}
return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
}
+ConstraintWrapperPtr createConstraintPointsCollinear(
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint3)
+{
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintPointOnLine(
+ *(thePoint1->point()), *(thePoint2->point()), *(thePoint3->point())));
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_ON_CURVE));
+}
+
+template <typename ARCTYPE>
+void createConstraintMiddlePointOnArc(ARCTYPE theArc,
+ GCSPointPtr thePoint,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters,
+ std::list<GCSConstraintPtr>& theConstraints)
+{
+ double* u = theAuxParameters->point()->x;
+ double* diff = theAuxParameters->point()->y;
+ *u = (*theArc->startAngle + *theArc->endAngle) * 0.5;
+ *diff = (*theArc->endAngle - *theArc->startAngle) * 0.5;
+
+ theConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(*thePoint, thePoint->x, *theArc, u)));
+ theConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintCurveValue(*thePoint, thePoint->y, *theArc, u)));
+ theConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintDifference(theArc->startAngle, u, diff)));
+ theConstraints.push_back(GCSConstraintPtr(
+ new GCS::ConstraintDifference(u, theArc->endAngle, diff)));
+}
+
ConstraintWrapperPtr createConstraintMiddlePoint(
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
- std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity)
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> theAuxParameters)
{
+ std::list<GCSConstraintPtr> aConstrList;
+
GCSPointPtr aPoint = thePoint->point();
std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
- if (!aLine)
- return ConstraintWrapperPtr();
-
- std::list<GCSConstraintPtr> aConstrList;
- aConstrList.push_back(
- GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
+ if (aLine) {
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
+ aConstrList.push_back(
+ GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
+ }
+ else {
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theEntity->entity());
+ if (anArc)
+ createConstraintMiddlePointOnArc(anArc, aPoint, theAuxParameters, aConstrList);
+ else {
+ std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEntity->entity());
+ if (aEllArc)
+ createConstraintMiddlePointOnArc(aEllArc, aPoint, theAuxParameters, aConstrList);
+ }
+ }
- return ConstraintWrapperPtr(
+ return aConstrList.empty() ? ConstraintWrapperPtr() : ConstraintWrapperPtr(
new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
}
{
std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
- GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
+
+ std::shared_ptr<GCS::Circle> aCirc1 =
+ std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
+ std::shared_ptr<GCS::Circle> aCirc2 =
+ std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
+
+ GCSConstraintPtr aNewConstr;
+ if (aLine1 && aLine2)
+ aNewConstr.reset(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
+ else {
+ if (aLine1 && aCirc2)
+ aCirc1 = aCirc2;
+ else if (aLine2 && aCirc1)
+ aLine1 = aLine2;
+
+ aNewConstr.reset(new GCS::ConstraintPointOnLine(aCirc1->center, *aLine1));
+ }
return ConstraintWrapperPtr(
new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
}
+ConstraintWrapperPtr createConstraintAngleBetweenCurves(
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity2)
+{
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintAngleViaPoint(
+ *theEntity1->entity(), *theEntity2->entity(), *thePoint->point(), theValue->scalar()));
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR_CURVES));
+}
+
ConstraintWrapperPtr createConstraintEqual(
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity1,
aConstrList.push_back(GCSConstraintPtr(
new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
// update value of intermediate parameter
- double x = *aLine1->p1.x - *aLine1->p2.x;
- double y = *aLine1->p1.y - *aLine1->p2.y;
- double aLen = sqrt(x*x + y*y);
- theIntermed->setValue(aLen);
- } else {
+ theIntermed->setValue(distance(aLine1->p1, aLine1->p2));
+ }
+ else if (theType == CONSTRAINT_EQUAL_ELLIPSES) {
+ std::shared_ptr<GCS::Ellipse> anEllipse1 =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEntity1->entity());
+ std::shared_ptr<GCS::Ellipse> anEllipse2 =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEntity2->entity());
+
+ aConstrList.push_back(GCSConstraintPtr(
+ new GCS::ConstraintEqual(anEllipse1->radmin, anEllipse2->radmin)));
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ anEllipse1->center, anEllipse1->focus1, theIntermed->scalar())));
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ anEllipse2->center, anEllipse2->focus1, theIntermed->scalar())));
+ // update value of intermediate parameter
+ theIntermed->setValue(distance(anEllipse1->center, anEllipse1->focus1));
+ }
+ else {
std::shared_ptr<GCS::Circle> aCirc1 =
std::dynamic_pointer_cast<GCS::Circle>(theEntity1->entity());
std::shared_ptr<GCS::Circle> aCirc2 =
std::dynamic_pointer_cast<GCS::Circle>(theEntity2->entity());
-
aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintEqual(aCirc1->rad, aCirc2->rad)));
}
GCS::SET_pD arcParameters(const EdgeWrapperPtr& theArc)
{
- GCS::SET_pD aParams;
+ GCS::SET_pD aParams = circleParameters(theArc);
std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(theArc->entity());
- aParams.insert(anArc->center.x);
- aParams.insert(anArc->center.y);
aParams.insert(anArc->start.x);
aParams.insert(anArc->start.y);
aParams.insert(anArc->end.x);
aParams.insert(anArc->end.y);
aParams.insert(anArc->startAngle);
aParams.insert(anArc->endAngle);
- aParams.insert(anArc->rad);
return aParams;
}
+
+GCS::SET_pD ellipseParameters(const EdgeWrapperPtr& theEllipse)
+{
+ GCS::SET_pD aParams;
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(theEllipse->entity());
+ aParams.insert(anEllipse->center.x);
+ aParams.insert(anEllipse->center.y);
+ aParams.insert(anEllipse->focus1.x);
+ aParams.insert(anEllipse->focus1.y);
+ aParams.insert(anEllipse->radmin);
+ return aParams;
+}
+
+GCS::SET_pD ellipticArcParameters(const EdgeWrapperPtr& theEllipticArc)
+{
+ GCS::SET_pD aParams = ellipseParameters(theEllipticArc);
+ std::shared_ptr<GCS::ArcOfEllipse> anArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(theEllipticArc->entity());
+ aParams.insert(anArc->start.x);
+ aParams.insert(anArc->start.y);
+ aParams.insert(anArc->end.x);
+ aParams.insert(anArc->end.y);
+ aParams.insert(anArc->startAngle);
+ aParams.insert(anArc->endAngle);
+ return aParams;
+}
+
+double distance(const GCS::Point& thePnt1, const GCS::Point& thePnt2)
+{
+ double x = *thePnt1.x - *thePnt2.x;
+ double y = *thePnt1.y - *thePnt2.y;
+ return sqrt(x*x + y*y);
+}
#include <SketchSolver_ConstraintMovement.h>
#include <SketchPlugin_Constraint.h>
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
+class GeomAPI_Circ2d;
+class GeomAPI_Ellipse2d;
+class GeomAPI_Lin2d;
+class GeomAPI_Pnt2d;
/** \namespace PlaneGCSSolver_Tools
* \ingroup Plugins
/// \brief Convert entity to line
/// \return empty pointer if the entity is not a line
std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity);
+ /// \brief Convert entity to circle
+ /// \return empty pointer if the entity is not a circle
+ std::shared_ptr<GeomAPI_Circ2d> circle(EntityWrapperPtr theEntity);
+ /// \brief Convert entity to ellipse
+ /// \return empty pointer if the entity is not an ellipse
+ std::shared_ptr<GeomAPI_Ellipse2d> ellipse(EntityWrapperPtr theEntity);
/// \brief Convert entity to line
/// \return empty pointer if the entity is not a line
std::shared_ptr<GeomAPI_Lin2d> line(FeaturePtr theFeature);
+ /// \brief Update start and end parameters of circular and elliptic arcs
+ /// respectively to start and end points on the arc.
+ /// For the circular arc, the radius is calculated too.
+ void recalculateArcParameters(EntityWrapperPtr theArc);
+
/// brief Return list of parameters for the given entity
GCS::SET_pD parameters(const EntityWrapperPtr& theEntity);
};
#include <SketchSolver_Constraint.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintMiddle.h>
void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
{
if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+ theFeature->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID() ||
theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() ||
theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
myCoincident.clear();
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchPlugin_ConstraintCollinear.h>
#include <SketchPlugin_ConstraintDistance.h>
#include <SketchPlugin_ConstraintEqual.h>
SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint)
{
const std::string& aType = theConstraint->getKind();
- if (aType == SketchPlugin_ConstraintCoincidence::ID())
+ if (aType == SketchPlugin_ConstraintCoincidence::ID() ||
+ aType == SketchPlugin_ConstraintCoincidenceInternal::ID())
return CONSTRAINT_COINCIDENCE;
else if (aType == SketchPlugin_ConstraintRigid::ID())
return CONSTRAINT_FIXED;
#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <GeomDataAPI_Point2D.h>
+
#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
static void getCoincidentFeatureExtremities(const ConstraintPtr& theConstraint,
const StoragePtr& theStorage,
} else if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
theExtremities[0] = theStorage->entity(aFeature->attribute(SketchPlugin_Arc::START_ID()));
theExtremities[1] = theStorage->entity(aFeature->attribute(SketchPlugin_Arc::END_ID()));
+ } else if (aFeature->getKind() == SketchPlugin_EllipticArc::ID()) {
+ theExtremities[0] = theStorage->entity(
+ aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ theExtremities[1] = theStorage->entity(
+ aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ }
+ }
+}
+
+static void getPointOwnerAndParent(const AttributeRefAttrPtr theRefAttr,
+ AttributePoint2DPtr& thePoint,
+ FeaturePtr& theOwner,
+ FeaturePtr& theParent)
+{
+ AttributePtr anAttr = theRefAttr->attr();
+ if (theRefAttr->isObject()) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theRefAttr->object());
+ if (anOwner && anOwner->getKind() == SketchPlugin_Point::ID())
+ anAttr = anOwner->attribute(SketchPlugin_Point::COORD_ID());
+ else
+ return;
+ }
+ thePoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+ if (thePoint) {
+ theOwner = ModelAPI_Feature::feature(thePoint->owner());
+ if (theOwner) {
+ std::string aParentRefID;
+ if (theOwner->getKind() == SketchPlugin_Line::ID())
+ aParentRefID = SketchPlugin_Line::PARENT_ID();
+ else if (theOwner->getKind() == SketchPlugin_Point::ID())
+ aParentRefID = SketchPlugin_Point::PARENT_ID();
+ if (!aParentRefID.empty()) {
+ AttributeReferencePtr aParentRef = theOwner->reference(aParentRefID);
+ theParent = aParentRef ? ModelAPI_Feature::feature(aParentRef->value()) : FeaturePtr();
+ }
}
}
}
+static void ellipseDiameters(FeaturePtr theEllipse,
+ std::pair<std::string, std::string>& theMajorAxis,
+ std::pair<std::string, std::string>& theMinorAxis)
+{
+ if (theEllipse->getKind() == SketchPlugin_Ellipse::ID()) {
+ theMajorAxis.first = SketchPlugin_Ellipse::MAJOR_AXIS_START_ID();
+ theMajorAxis.second = SketchPlugin_Ellipse::MAJOR_AXIS_END_ID();
+ theMinorAxis.first = SketchPlugin_Ellipse::MINOR_AXIS_START_ID();
+ theMinorAxis.second = SketchPlugin_Ellipse::MINOR_AXIS_END_ID();
+ } else if (theEllipse->getKind() == SketchPlugin_EllipticArc::ID()) {
+ theMajorAxis.first = SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID();
+ theMajorAxis.second = SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID();
+ theMinorAxis.first = SketchPlugin_EllipticArc::MINOR_AXIS_START_ID();
+ theMinorAxis.second = SketchPlugin_EllipticArc::MINOR_AXIS_END_ID();
+ }
+}
+
+static void findDiameterOnEllipse(FeaturePtr theConstruction,
+ FeaturePtr theEllipse,
+ AttributePtr& theStart,
+ AttributePtr& theEnd)
+{
+ AttributePtr anEllipseAttr;
+ const std::set<AttributePtr>& aRefs = theConstruction->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
+ aRefIt != aRefs.end(); ++aRefIt) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+ if (anOwner && anOwner->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
+ AttributeRefAttrPtr aRefAttr;
+ if ((*aRefIt)->id() == SketchPlugin_Constraint::ENTITY_A())
+ aRefAttr = anOwner->refattr(SketchPlugin_Constraint::ENTITY_B());
+ else
+ aRefAttr = anOwner->refattr(SketchPlugin_Constraint::ENTITY_A());
+ anEllipseAttr = aRefAttr->attr();
+ break;
+ }
+ }
+ if (!anEllipseAttr)
+ return;
+
+ std::pair<std::string, std::string> aMajorAxis, aMinorAxis;
+ ellipseDiameters(theEllipse, aMajorAxis, aMinorAxis);
+ if (anEllipseAttr->id() == aMajorAxis.first) {
+ theStart = anEllipseAttr;
+ theEnd = theEllipse->attribute(aMajorAxis.second);
+ }
+ else if (anEllipseAttr->id() == aMajorAxis.second) {
+ theStart = theEllipse->attribute(aMajorAxis.first);
+ theEnd = anEllipseAttr;
+ }
+ else if (anEllipseAttr->id() == aMinorAxis.first) {
+ theStart = anEllipseAttr;
+ theEnd = theEllipse->attribute(aMinorAxis.second);
+ }
+ else if (anEllipseAttr->id() == aMinorAxis.second) {
+ theStart = theEllipse->attribute(aMinorAxis.first);
+ theEnd = anEllipseAttr;
+ }
+}
+
+static void processEllipticArcExtremities(SketchSolver_ConstraintType& theType,
+ const ConstraintPtr& theConstraint,
+ const StoragePtr& theStorage,
+ std::vector<EntityWrapperPtr>& theAttributes,
+ EntityWrapperPtr theExtremities[2])
+{
+ AttributePoint2DPtr aPointA, aPointB;
+ FeaturePtr anOwnerA, anOwnerB;
+ FeaturePtr aParentA, aParentB;
+ getPointOwnerAndParent(theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()),
+ aPointA, anOwnerA, aParentA);
+ getPointOwnerAndParent(theConstraint->refattr(SketchPlugin_Constraint::ENTITY_B()),
+ aPointB, anOwnerB, aParentB);
+
+ AttributePtr anAxisStart, anAxisEnd, aPoint;
+ FeaturePtr aConstruction, anEllipticArc;
+ if (aParentA && aParentA == anOwnerB) {
+ aPoint = aPointB;
+ aConstruction = anOwnerA;
+ anEllipticArc = anOwnerB;
+ }
+ else if (aParentB && aParentB == anOwnerA) {
+ aPoint = aPointA;
+ aConstruction = anOwnerB;
+ anEllipticArc = anOwnerA;
+ }
+
+ if (!anEllipticArc || anEllipticArc->getKind() != SketchPlugin_EllipticArc::ID() ||
+ (aPoint->id() != SketchPlugin_EllipticArc::START_POINT_ID() &&
+ aPoint->id() != SketchPlugin_EllipticArc::END_POINT_ID()))
+ return;
+
+ findDiameterOnEllipse(aConstruction, anEllipticArc, anAxisStart, anAxisEnd);
+
+ if (anAxisStart && anAxisEnd) {
+ theAttributes[0] = theStorage->entity(aPoint);
+ theAttributes[1] = theStorage->entity(anAxisStart);
+ theAttributes[2] = theStorage->entity(anAxisEnd);
+ theType = CONSTRAINT_PT_ON_CURVE;
+ getCoincidentFeatureExtremities(theConstraint, theStorage, theExtremities);
+ }
+}
+
void SketchSolver_ConstraintCoincidence::process()
{
return;
}
- if (theAttributes[1])
+ if (theAttributes[1]) {
myType = CONSTRAINT_PT_PT_COINCIDENT;
- else if (theAttributes[2]) {
- // check the type of entity (line or circle)
- SketchSolver_EntityType anEntType = theAttributes[2]->type();
- if (anEntType == ENTITY_LINE)
- myType = CONSTRAINT_PT_ON_LINE;
- else if (anEntType == ENTITY_CIRCLE || anEntType == ENTITY_ARC)
- myType = CONSTRAINT_PT_ON_CIRCLE;
- else
- myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
-
+ // if elliptic arc boundary point is connected with one of ellipse characteristics,
+ // it should be changed from point-point coincidence to coincidence between point
+ // and axis of the ellipse to decrease only 1 DoF instead of 2 DoF and avoid overconstraint.
+ processEllipticArcExtremities(myType, myBaseConstraint, myStorage,
+ theAttributes, myFeatureExtremities);
+ } else if (theAttributes[2]) {
+ myType = CONSTRAINT_PT_ON_CURVE;
// obtain extremity points of the coincident feature for further checking of multi-coincidence
getCoincidentFeatureExtremities(myBaseConstraint, myStorage, myFeatureExtremities);
} else
PlaneGCSSolver_UpdateCoincidence* anUpdater =
static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back());
+ // additionally process internal coincidence, set point coincident with ellipse/elliptic arc
+ // for correct processing further coincidences set by the user
+ if (isAccepted &&
+ myBaseConstraint->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
+ AttributeRefAttrPtr aRefAttrA = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr aRefAttrB = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+ if (aRefAttrA && aRefAttrB) {
+ AttributePoint2DPtr anAttrA, anAttrB;
+ FeaturePtr anOwnerA, anOwnerB;
+ FeaturePtr aParentA, aParentB;
+ getPointOwnerAndParent(aRefAttrA, anAttrA, anOwnerA, aParentA);
+ getPointOwnerAndParent(aRefAttrB, anAttrB, anOwnerB, aParentB);
+
+ EntityWrapperPtr aPoint, anEntity;
+ if (aParentA == anOwnerB) {
+ aPoint = myStorage->entity(anAttrA);
+ anEntity = myStorage->entity(anOwnerB);
+ }
+ else if (aParentB == anOwnerA) {
+ aPoint = myStorage->entity(anAttrB);
+ anEntity = myStorage->entity(anOwnerA);
+ }
+ if (aPoint && anEntity)
+ anUpdater->addCoincidence(aPoint, anEntity);
+ }
+ }
// additionally check the point is coincident to extremity of coincident feature
if (myFeatureExtremities[0] && myFeatureExtremities[1]) {
int aNbLines = 0;
int aNbArcs = 0;
int aNbCircs = 0;
+ int aNbEllipses = 0;
bool isArcFirst = false; // in line-arc equivalence, the line should be first
std::vector<EntityWrapperPtr>::iterator anAttrIt = theAttributes.begin() + 2;
for (; anAttrIt != theAttributes.end(); ++anAttrIt) {
++aNbArcs;
isArcFirst = (aNbLines == 0);
}
+ else if (aType == ENTITY_ELLIPSE || aType == ENTITY_ELLIPTIC_ARC)
+ ++aNbEllipses;
}
- if (aNbLines + aNbArcs + aNbCircs != 2 ||
- (aNbLines == aNbCircs && aNbArcs == 0)) {
+ if (aNbLines + aNbArcs + aNbCircs + aNbEllipses != 2 ||
+ (aNbArcs == 1 && aNbEllipses != 0) || aNbEllipses == 1) {
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
return;
}
switch (aNbLines) {
case 0:
- myType = CONSTRAINT_EQUAL_RADIUS;
+ if (aNbEllipses == 2) {
+ myType = CONSTRAINT_EQUAL_ELLIPSES;
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+ myAuxValue = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(aStorage->createParameter()));
+ theValue = myAuxValue;
+ }
+ else
+ myType = CONSTRAINT_EQUAL_RADIUS;
break;
case 1:
myType = CONSTRAINT_EQUAL_LINE_ARC;
break;
}
}
+
+bool SketchSolver_ConstraintEqual::remove()
+{
+ if (myAuxValue) {
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+ GCS::SET_pD aParams;
+ aParams.insert(myAuxValue->scalar());
+ aStorage->removeParameters(aParams);
+ }
+ return SketchSolver_Constraint::remove();
+}
SketchSolver_Constraint(theConstraint)
{}
+ /// \brief Tries to remove constraint
+ /// \return \c false, if current constraint contains another SketchPlugin constraints
+ /// (like for multiple coincidence)
+ virtual bool remove();
+
protected:
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
virtual void getAttributes(EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes);
+
+private:
+ ScalarWrapperPtr myAuxValue; ///< scalar value to store ellipses focus distance
};
#endif
aParameters.push_back(anArc->endAngle);
break;
}
+ case ENTITY_ELLIPSE: {
+ std::shared_ptr<GCS::Ellipse> anEllipse =
+ std::dynamic_pointer_cast<GCS::Ellipse>(anEntity->entity());
+ aParameters.push_back(anEllipse->center.x);
+ aParameters.push_back(anEllipse->center.y);
+ aParameters.push_back(anEllipse->focus1.x);
+ aParameters.push_back(anEllipse->focus1.y);
+ aParameters.push_back(anEllipse->radmin);
+ break;
+ }
+ case ENTITY_ELLIPTIC_ARC: {
+ std::shared_ptr<GCS::ArcOfEllipse> anEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anEntity->entity());
+ aParameters.push_back(anEllArc->center.x);
+ aParameters.push_back(anEllArc->center.y);
+ aParameters.push_back(anEllArc->focus1.x);
+ aParameters.push_back(anEllArc->focus1.y);
+ aParameters.push_back(anEllArc->radmin);
+ aParameters.push_back(anEllArc->startAngle);
+ aParameters.push_back(anEllArc->endAngle);
+ break;
+ }
default:
break;
}
#include <SketchSolver_ConstraintMiddle.h>
#include <PlaneGCSSolver_ConstraintWrapper.h>
+#include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_Storage.h>
+#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_UpdateCoincidence.h>
+static bool isArc(EntityWrapperPtr theEntity)
+{
+ return theEntity->type() == ENTITY_ARC || theEntity->type() == ENTITY_ELLIPTIC_ARC;
+}
+
void SketchSolver_ConstraintMiddle::getAttributes(
EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
+
+ // create auxiliary point if middle point on arc is specified
+ if (isArc(theAttributes[2])) {
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+
+ myOddPoint = GCSPointPtr(new GCS::Point);
+ myOddPoint->x = aStorage->createParameter();
+ myOddPoint->y = aStorage->createParameter();
+ theAttributes[1] = PointWrapperPtr(new PlaneGCSSolver_PointWrapper(myOddPoint));
+ }
+}
+
+bool SketchSolver_ConstraintMiddle::remove()
+{
+ if (myOddPoint) {
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+
+ GCS::SET_pD aParams;
+ aParams.insert(myOddPoint->x);
+ aParams.insert(myOddPoint->y);
+ aStorage->removeParameters(aParams);
+ }
+ return SketchSolver_ConstraintCoincidence::remove();
}
void SketchSolver_ConstraintMiddle::notify(const FeaturePtr& theFeature,
PlaneGCSSolver_Update* theUpdater)
{
- if (theFeature == myBaseConstraint && myInSolver)
- return; // the constraint is already being updated
+ if (theFeature == myBaseConstraint && myInSolver) {
+ // the constraint is already being updated,
+ // update the middle point parameter if the constraint is "point-on-arc".
+ if (myOddPoint) {
+ EntityWrapperPtr anArcEntity =
+ isArc(myAttributes.front()) ? myAttributes.front() : myAttributes.back();
+ EdgeWrapperPtr anArcEdge =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(anArcEntity);
+ if (anArcEdge) {
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEdge->entity());
+ if (anArc) {
+ // recalculate parameters of middle point according to arc
+ *myOddPoint->x = (*anArc->startAngle + *anArc->endAngle) * 0.5;
+ *myOddPoint->y = (*anArc->endAngle - *anArc->startAngle) * 0.5;
+ }
+ else {
+ std::shared_ptr<GCS::ArcOfEllipse> aEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(anArcEdge->entity());
+ if (aEllArc) {
+ // recalculate parameters of middle point according to arc
+ *myOddPoint->x = (*aEllArc->startAngle + *aEllArc->endAngle) * 0.5;
+ *myOddPoint->y = (*aEllArc->endAngle - *aEllArc->startAngle) * 0.5;
+ }
+ }
+ }
+ }
+ return;
+ }
PlaneGCSSolver_UpdateCoincidence* anUpdater =
static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
// remove previously adde constraint
myStorage->removeConstraint(myBaseConstraint);
// merge divided constraints into single object
- std::list<GCSConstraintPtr> aGCSConstraints;
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(myMiddle);
- aGCSConstraints.push_back(aConstraint->constraints().front());
- aConstraint =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(mySolverConstraint);
- aGCSConstraints.push_back(aConstraint->constraints().front());
+ std::list<GCSConstraintPtr> aGCSConstraints = myMiddle->constraints();
+ aGCSConstraints.push_front(mySolverConstraint->constraints().front());
myMiddle = ConstraintWrapperPtr();
mySolverConstraint = ConstraintWrapperPtr(
std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(mySolverConstraint);
std::list<GCSConstraintPtr> aGCSConstraints = aConstraint->constraints();
- myMiddle = ConstraintWrapperPtr(
- new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.front(), CONSTRAINT_MIDDLE_POINT));
mySolverConstraint = ConstraintWrapperPtr(
- new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.back(), CONSTRAINT_MIDDLE_POINT));
+ new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.front(), CONSTRAINT_MIDDLE_POINT));
+ aGCSConstraints.pop_front();
+ myMiddle = ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints, CONSTRAINT_MIDDLE_POINT));
// send middle constraint only
myStorage->addConstraint(myBaseConstraint, myMiddle);
virtual void notify(const FeaturePtr& theFeature,
PlaneGCSSolver_Update* theUpdater);
+ /// \brief Remove constraint
+ virtual bool remove();
+
protected:
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
private:
ConstraintWrapperPtr myMiddle;
+ GCSPointPtr myOddPoint; ///< auxiliary point to adjust midpoint-on-arc
};
#endif
#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_UpdateFeature.h>
+#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeRefList.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_EllipticArc.h>
static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
}
+ else if (theOriginal->getKind() == SketchPlugin_EllipticArc::ID()) {
+ // orientation of arc
+ theMirrored->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->setValue(
+ !theOriginal->boolean(SketchPlugin_EllipticArc::REVERSED_ID())->value());
+ }
// mirror all initialized points of features
std::list<AttributePtr>::iterator anIt0, anIt1;
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
#include <GeomAPI_Pnt2d.h>
+#include <cmath>
+
+static GCS::Point createGCSPoint(double* x, double* y)
+{
+ GCS::Point aPoint;
+ aPoint.x = x;
+ aPoint.y = y;
+ return aPoint;
+}
+
SketchSolver_ConstraintMovement::SketchSolver_ConstraintMovement(FeaturePtr theFeature)
: SketchSolver_ConstraintFixed(ConstraintPtr()),
{
bool isSimple = true;
#ifdef CHANGE_RADIUS_WHILE_MOVE
- if (theMovedFeature->getKind() == SketchPlugin_Circle::ID())
+ if (theMovedFeature->getKind() == SketchPlugin_Circle::ID() ||
+ theMovedFeature->getKind() == SketchPlugin_Ellipse::ID())
isSimple = (theDraggedPoint.get() != 0);
- else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID()) {
+ else if (theMovedFeature->getKind() == SketchPlugin_Arc::ID() ||
+ theMovedFeature->getKind() == SketchPlugin_EllipticArc::ID()) {
isSimple = (theDraggedPoint.get() != 0 &&
- theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID());
+ (theDraggedPoint->id() == SketchPlugin_Arc::CENTER_ID() ||
+ theDraggedPoint->id() == SketchPlugin_EllipticArc::CENTER_ID()));
}
#endif
return isSimple;
else {
if (myDraggedPoint) // start or end point of arc has been moved
aConstraint = fixArcExtremity(anEntity);
- else // arc or circle has been moved
+ else if (anEntity->type() == ENTITY_CIRCLE || anEntity->type() == ENTITY_ARC) {
+ // arc or circle has been moved
aConstraint = fixPointOnCircle(anEntity);
+ }
+ else if (anEntity->type() == ENTITY_ELLIPSE || anEntity->type() == ENTITY_ELLIPTIC_ARC) {
+ // ellipse or elliptic arc has been moved
+ aConstraint = fixPointOnEllipse(anEntity);
+ }
}
return aConstraint;
myStorage->entity(myMovedFeature));
std::shared_ptr<GCS::Arc> anArc =
std::dynamic_pointer_cast<GCS::Arc>(aCircularEntity->entity());
+ std::shared_ptr<GCS::ArcOfEllipse> anEllArc =
+ std::dynamic_pointer_cast<GCS::ArcOfEllipse>(aCircularEntity->entity());
PointWrapperPtr aPoint =
std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theArcExtremity);
- double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y,
- anArc->center.x, anArc->center.y };
+ double* aParams[nbParams] = { aPoint->point()->x, aPoint->point()->y, 0, 0 };
+ if (anArc) {
+ aParams[2] = anArc->center.x;
+ aParams[3] = anArc->center.y;
+ }
+ else if (anEllArc) {
+ aParams[2] = anEllArc->center.x;
+ aParams[3] = anEllArc->center.y;
+ }
std::list<GCSConstraintPtr> aConstraints;
for (int i = 0; i < nbParams; ++i) {
myFixedValues.push_back(*aCircular->center.y);
// create a moved point
- GCS::Point aPointOnCircle;
- aPointOnCircle.x = &myFixedValues[0];
- aPointOnCircle.y = &myFixedValues[1];
+ GCS::Point aPointOnCircle = createGCSPoint(&myFixedValues[0], &myFixedValues[1]);
std::list<GCSConstraintPtr> aConstraints;
// point-on-circle
new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
}
+ConstraintWrapperPtr SketchSolver_ConstraintMovement::fixPointOnEllipse(
+ const EntityWrapperPtr& theConic)
+{
+ static const double scale = 0.01;
+ static const int nbParams = 6;
+ myFixedValues.reserve(nbParams); // moved point; center and focus of ellipse
+
+ EdgeWrapperPtr anEdge = std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theConic);
+ std::shared_ptr<GCS::Ellipse> aConic = std::dynamic_pointer_cast<GCS::Ellipse>(anEdge->entity());
+
+ // major axis direction
+ double dx = *aConic->focus1.x - *aConic->center.x;
+ double dy = *aConic->focus1.y - *aConic->center.y;
+ double norm = sqrt(dx * dx + dy* dy);
+ if (norm < tolerance) {
+ dx = 1.0;
+ dy = 0.0;
+ }
+ else {
+ dx /= norm;
+ dy /= norm;
+ }
+
+ double aMajorRad = aConic->getRadMaj();
+
+ // initialize fixed values
+ myFixedValues.push_back(*aConic->center.x + dx * aMajorRad);
+ myFixedValues.push_back(*aConic->center.y + dy * aMajorRad);
+ myFixedValues.push_back(*aConic->center.x);
+ myFixedValues.push_back(*aConic->center.y);
+ myFixedValues.push_back(*aConic->focus1.x);
+ myFixedValues.push_back(*aConic->focus1.y);
+
+ // create a moved point
+ GCS::Point aPointOnEllipse = createGCSPoint(&myFixedValues[0], &myFixedValues[1]);
+
+ std::list<GCSConstraintPtr> aConstraints;
+ // point-on-circle
+ GCSConstraintPtr aNewConstraint(
+ new GCS::ConstraintPointOnEllipse(aPointOnEllipse, *aConic));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // fixed center (x)
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintEqual(&myFixedValues[2], aConic->center.x));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // fixed center (y)
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintEqual(&myFixedValues[3], aConic->center.y));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+ // focus on the major axis
+ GCS::Point aStartPoint = createGCSPoint(&myFixedValues[2], &myFixedValues[3]);
+ GCS::Point aEndPoint = createGCSPoint(&myFixedValues[4], &myFixedValues[5]);
+ aNewConstraint = GCSConstraintPtr(
+ new GCS::ConstraintPointOnLine(aConic->focus1, aStartPoint, aEndPoint));
+ aNewConstraint->rescale(scale);
+ aConstraints.push_back(aNewConstraint);
+
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
+}
void SketchSolver_ConstraintMovement::startPoint(
const std::shared_ptr<GeomAPI_Pnt2d>& theStartPoint)
/// \brief Create constraint to fix moved arc extremity
ConstraintWrapperPtr fixArcExtremity(const EntityWrapperPtr& theArcExtremity);
- /// \brief Creat constraint to fix moved point on circle/arc
+ /// \brief Create constraint to fix moved point on circle/arc
ConstraintWrapperPtr fixPointOnCircle(const EntityWrapperPtr& theCircular);
+ /// \brief Create constraint to fix moved point on ellipse/elliptic arc
+ ConstraintWrapperPtr fixPointOnEllipse(const EntityWrapperPtr& theConic);
+
private:
FeaturePtr myMovedFeature; ///< fixed feature (if set, myBaseConstraint should be NULL)
AttributePtr myDraggedPoint; ///< one of the feature points which has been moved
--- /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 <SketchSolver_ConstraintPerpendicular.h>
+#include <SketchSolver_Error.h>
+
+#include <PlaneGCSSolver_EdgeWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_Storage.h>
+#include <PlaneGCSSolver_Tools.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+
+#include <GeomAPI_Circ2d.h>
+#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_Ellipse2d.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintMiddle.h>
+
+#include <cmath>
+
+#define GCS_EDGE_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(x)
+#define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
+
+/// \brief Obtain constrained features
+static void getFeatures(const ConstraintPtr& theConstraint,
+ FeaturePtr& theFeature1,
+ FeaturePtr& theFeature2);
+
+/// \brief Check whether the entities has only one shared point or less.
+/// Return list of coincident points.
+static std::set<AttributePtr> coincidentBoundaryPoints(FeaturePtr theFeature1,
+ FeaturePtr theFeature2);
+
+/// \brief Collect points coincident with each of two features
+static std::set<AttributePtr> coincidentPoints(FeaturePtr theFeature1, FeaturePtr theFeature2);
+
+static void calculateIntersectionPoint(EntityWrapperPtr theCurve1, EntityWrapperPtr theCurve2,
+ GCSPointPtr& theIntersectionPoint);
+
+/// sets angle to 90 or -90 degrees
+static void adjustAngleBetweenCurves(const GCSCurvePtr& theCurve1,
+ const GCSCurvePtr& theCurve2,
+ const GCSPointPtr& thePoint,
+ double* theAngle);
+
+
+void SketchSolver_ConstraintPerpendicular::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage) {
+ // Not enough parameters are assigned
+ return;
+ }
+
+ EntityWrapperPtr aValue;
+ std::vector<EntityWrapperPtr> anAttributes;
+ SketchSolver_Constraint::getAttributes(aValue, anAttributes);
+ if (!myErrorMsg.empty())
+ return;
+
+ rebuild();
+ if (!myErrorMsg.empty())
+ return;
+
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
+}
+
+void SketchSolver_ConstraintPerpendicular::rebuild()
+{
+ if (mySolverConstraint)
+ myStorage->removeConstraint(myBaseConstraint);
+
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+
+ mySolverConstraint = ConstraintWrapperPtr();
+ mySharedPoint = AttributePtr();
+ if (myAuxPoint) {
+ GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(myAuxPoint);
+ aStorage->removeParameters(aParams);
+ myAuxPoint = EntityWrapperPtr();
+ }
+
+ // Check the quantity of entities of each type and their order (arcs first)
+ int aNbLines = 0;
+ int aNbCircles = 0;
+ int aNbOther = 0;
+ std::list<EntityWrapperPtr>::iterator anEntIt = myAttributes.begin();
+ for (; anEntIt != myAttributes.end(); ++anEntIt) {
+ if (!(*anEntIt).get())
+ continue;
+ if ((*anEntIt)->type() == ENTITY_LINE)
+ ++aNbLines;
+ else if ((*anEntIt)->type() == ENTITY_ARC || (*anEntIt)->type() == ENTITY_CIRCLE)
+ ++aNbCircles;
+ else if ((*anEntIt)->type() != ENTITY_POINT)
+ ++aNbOther;
+ }
+
+ if (aNbLines + aNbCircles + aNbOther == 2) {
+ if (aNbOther > 0)
+ myType = CONSTRAINT_PERPENDICULAR_CURVES;
+ }
+ else {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ FeaturePtr aFeature1, aFeature2;
+ getFeatures(myBaseConstraint, aFeature1, aFeature2);
+
+ // check number of coincident points
+ std::set<AttributePtr> aCoincidentPoints = coincidentBoundaryPoints(aFeature1, aFeature2);
+ // Try to find non-boundary points coincident with both features.
+ // It is necesasry to create perpendicularity with ellipse
+ if (aCoincidentPoints.empty() && aNbOther > 0)
+ aCoincidentPoints = coincidentPoints(aFeature1, aFeature2);
+
+ EntityWrapperPtr aSharedPointEntity;
+ std::list<GCSConstraintPtr> anAuxConstraints;
+ if (!aCoincidentPoints.empty()) {
+ mySharedPoint = *aCoincidentPoints.begin();
+ aSharedPointEntity = myStorage->entity(mySharedPoint);
+ }
+ else if (aNbOther > 0) {
+ // create auxiliary point
+ GCSPointPtr aPoint(new GCS::Point);
+ aPoint->x = aStorage->createParameter();
+ aPoint->y = aStorage->createParameter();
+ calculateIntersectionPoint(myAttributes.front(), myAttributes.back(), aPoint);
+
+ myAuxPoint.reset(new PlaneGCSSolver_PointWrapper(aPoint));
+ aSharedPointEntity = myAuxPoint;
+
+ // create auxiliary coincident constraints for tangency with ellipse
+ EntityWrapperPtr aDummy;
+ ConstraintWrapperPtr aCoincidence = PlaneGCSSolver_Tools::createConstraint(ConstraintPtr(),
+ CONSTRAINT_PT_ON_CURVE, aDummy, aSharedPointEntity, aDummy, myAttributes.front(), aDummy);
+ anAuxConstraints = aCoincidence->constraints();
+ aCoincidence = PlaneGCSSolver_Tools::createConstraint(ConstraintPtr(),
+ CONSTRAINT_PT_ON_CURVE, aDummy, aSharedPointEntity, aDummy, myAttributes.back(), aDummy);
+ anAuxConstraints.insert(anAuxConstraints.end(),
+ aCoincidence->constraints().begin(), aCoincidence->constraints().end());
+ }
+
+ ScalarWrapperPtr anAngleWrapper;
+ if (aSharedPointEntity) {
+ adjustAngleBetweenCurves(GCS_EDGE_WRAPPER(myAttributes.front())->entity(),
+ GCS_EDGE_WRAPPER(myAttributes.back())->entity(),
+ GCS_POINT_WRAPPER(aSharedPointEntity)->point(), &myCurveCurveAngle);
+ anAngleWrapper.reset(new PlaneGCSSolver_ScalarWrapper(&myCurveCurveAngle));
+ }
+
+ mySolverConstraint = PlaneGCSSolver_Tools::createConstraint(myBaseConstraint, myType,
+ anAngleWrapper, aSharedPointEntity, EntityWrapperPtr(),
+ myAttributes.front(), myAttributes.back());
+
+ if (!anAuxConstraints.empty()) {
+ anAuxConstraints.insert(anAuxConstraints.end(), mySolverConstraint->constraints().begin(),
+ mySolverConstraint->constraints().end());
+ mySolverConstraint->setConstraints(anAuxConstraints);
+ }
+
+ myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
+}
+
+void SketchSolver_ConstraintPerpendicular::notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update* theUpdater)
+{
+ if (theFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
+ return;
+
+ // base constraint may become invalid (for example, during undo)
+ if (!myBaseConstraint->data() || !myBaseConstraint->data()->isValid())
+ return;
+
+ FeaturePtr aTgFeat1, aTgFeat2;
+ getFeatures(myBaseConstraint, aTgFeat1, aTgFeat2);
+
+ bool isRebuild = false;
+ if (theFeature->data() && theFeature->data()->isValid()) {
+ // the constraint has been created
+ if (!mySharedPoint) {
+ // features has no shared point, check whether coincidence constraint binds these features)
+ int aNbCoincidentFeatures = 0;
+ for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+ AttributeRefAttrPtr aRefAttr = theFeature->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+ if (!aRefAttr)
+ continue;
+
+ ObjectPtr anObj;
+ if (aRefAttr->isObject())
+ anObj = aRefAttr->object();
+ else
+ anObj = aRefAttr->attr()->owner();
+
+ FeaturePtr aFeature = ModelAPI_Feature::feature(anObj);
+ if (aFeature == aTgFeat1 || aFeature == aTgFeat2)
+ ++aNbCoincidentFeatures;
+ }
+
+ if (aNbCoincidentFeatures == 2)
+ isRebuild = true;
+ }
+ }
+
+ if (!isRebuild) {
+ if (mySharedPoint) {
+ // The features are tangent in the shared point, but the coincidence has been removed/updated.
+ // Check if the coincidence is the same.
+ std::set<AttributePtr> aCoincidentPoints = coincidentBoundaryPoints(aTgFeat1, aTgFeat2);
+ isRebuild = true;
+ std::set<AttributePtr>::iterator anIt = aCoincidentPoints.begin();
+ for (; anIt != aCoincidentPoints.end() && isRebuild; ++anIt)
+ if (*anIt == mySharedPoint)
+ isRebuild = false; // the coincidence is still exists => nothing to change
+ }
+ else {
+ // check both features have a coincident point
+ std::set<AttributePtr> aCoincidentPoints = coincidentPoints(aTgFeat1, aTgFeat2);
+ isRebuild = (bool)(myAuxPoint.get()) == (!aCoincidentPoints.empty());
+ }
+ }
+
+ if (isRebuild)
+ rebuild();
+}
+
+
+
+
+// ================== Auxiliary functions =================================
+void getFeatures(const ConstraintPtr& theConstraint,
+ FeaturePtr& theFeature1,
+ FeaturePtr& theFeature2)
+{
+ AttributeRefAttrPtr aRefAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ theFeature1 = ModelAPI_Feature::feature(aRefAttr->object());
+ aRefAttr = theConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+ theFeature2 = ModelAPI_Feature::feature(aRefAttr->object());
+}
+
+static std::set<FeaturePtr> collectCoincidences(FeaturePtr theFeature1, FeaturePtr theFeature2)
+{
+ const std::set<AttributePtr>& aRefs1 = theFeature1->data()->refsToMe();
+ const std::set<AttributePtr>& aRefs2 = theFeature2->data()->refsToMe();
+
+ std::set<FeaturePtr> aCoincidences;
+ std::set<AttributePtr>::const_iterator anIt;
+
+ // collect coincidences referred to the first feature
+ for (anIt = aRefs1.begin(); anIt != aRefs1.end(); ++anIt) {
+ FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aRef && aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+ aCoincidences.insert(aRef);
+ }
+
+ // leave only coincidences referred to the second feature
+ std::set<FeaturePtr> aCoincidencesBetweenFeatures;
+ for (anIt = aRefs2.begin(); anIt != aRefs2.end(); ++anIt) {
+ FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aCoincidences.find(aRef) != aCoincidences.end())
+ aCoincidencesBetweenFeatures.insert(aRef);
+ }
+
+ return aCoincidencesBetweenFeatures;
+}
+
+std::set<AttributePtr> coincidentBoundaryPoints(FeaturePtr theFeature1, FeaturePtr theFeature2)
+{
+ std::set<FeaturePtr> aCoincidences = collectCoincidences(theFeature1, theFeature2);
+ // collect points only
+ std::set<AttributePtr> aCoincidentPoints;
+ std::set<FeaturePtr>::const_iterator aCIt = aCoincidences.begin();
+ for (; aCIt != aCoincidences.end(); ++ aCIt) {
+ AttributeRefAttrPtr aRefAttrA = (*aCIt)->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr aRefAttrB = (*aCIt)->refattr(SketchPlugin_Constraint::ENTITY_B());
+ if (!aRefAttrA || aRefAttrA->isObject() ||
+ !aRefAttrB || aRefAttrB->isObject())
+ continue;
+
+ AttributePtr anAttrA = aRefAttrA->attr();
+ AttributePtr anAttrB = aRefAttrB->attr();
+ if (anAttrA->id() != SketchPlugin_Arc::CENTER_ID() &&
+ anAttrA->id() != SketchPlugin_Circle::CENTER_ID() &&
+ anAttrB->id() != SketchPlugin_Arc::CENTER_ID() &&
+ anAttrB->id() != SketchPlugin_Circle::CENTER_ID()) {
+ aCoincidentPoints.insert(anAttrA);
+ aCoincidentPoints.insert(anAttrB);
+ }
+ }
+ return aCoincidentPoints;
+}
+
+static std::set<AttributePtr> refsToFeatureAndResults(FeaturePtr theFeature)
+{
+ std::set<AttributePtr> aRefs = theFeature->data()->refsToMe();
+ const std::list<ResultPtr>& aResults = theFeature->results();
+ for (std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+ anIt != aResults.end(); ++anIt) {
+ const std::set<AttributePtr>& aResRefs = (*anIt)->data()->refsToMe();
+ aRefs.insert(aResRefs.begin(), aResRefs.end());
+ }
+ return aRefs;
+}
+
+// collect all points coincident with the feature
+static std::set<AttributePtr> pointsOnFeature(FeaturePtr theFeature)
+{
+ std::set<AttributePtr> aPoints;
+
+ std::set<AttributePtr> aRefs = refsToFeatureAndResults(theFeature);
+ for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) {
+ FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aRef && (aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+ aRef->getKind() == SketchPlugin_ConstraintMiddle::ID())) {
+ for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+ AttributeRefAttrPtr aRefAttr = aRef->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+ if (aRefAttr) {
+ AttributePtr anAttr = aRefAttr->attr();
+ if (anAttr && anAttr->id() != SketchPlugin_Arc::CENTER_ID() &&
+ anAttr->id() != SketchPlugin_Circle::CENTER_ID())
+ aPoints.insert(anAttr);
+ }
+ }
+ }
+ }
+ return aPoints;
+}
+
+std::set<AttributePtr> coincidentPoints(FeaturePtr theFeature1, FeaturePtr theFeature2)
+{
+ std::set<AttributePtr> aPointsOnF1 = pointsOnFeature(theFeature1);
+ std::set<AttributePtr> aPointsOnF2 = pointsOnFeature(theFeature2);
+
+ std::set<AttributePtr> aCommonPoints;
+ for (std::set<AttributePtr>::iterator anIt = aPointsOnF1.begin();
+ anIt != aPointsOnF1.end(); ++anIt)
+ if (aPointsOnF2.find(*anIt) != aPointsOnF2.end())
+ aCommonPoints.insert(*anIt);
+ return aCommonPoints;
+}
+
+void adjustAngleBetweenCurves(const GCSCurvePtr& theCurve1,
+ const GCSCurvePtr& theCurve2,
+ const GCSPointPtr& thePoint,
+ double* theAngle)
+{
+ double anAngle = GCS::System().calculateAngleViaPoint(*theCurve1, *theCurve2, *thePoint);
+ // bring angle to [-pi..pi]
+ if (anAngle > PI) anAngle -= 2.0 * PI;
+ if (anAngle < -PI) anAngle += 2.0 * PI;
+ // set angle value according to the current angle between curves
+ if (anAngle >= 0)
+ *theAngle = PI / 2.;
+ else
+ *theAngle = -PI / 2.;
+}
+
+void calculateIntersectionPoint(EntityWrapperPtr theCurve1, EntityWrapperPtr theCurve2,
+ GCSPointPtr& theIntersectionPoint)
+{
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse = PlaneGCSSolver_Tools::ellipse(theCurve1);
+ EntityWrapperPtr aCurve2 = theCurve2;
+ if (!anEllipse) {
+ // try converting to ellipse the second curve
+ anEllipse = PlaneGCSSolver_Tools::ellipse(theCurve2);
+ if (!anEllipse)
+ return; // no one curve is ellipse
+ aCurve2 = theCurve1;
+ }
+
+ GeomPnt2dPtr aP1, aP2;
+ if (aCurve2->type() == ENTITY_LINE) {
+ std::shared_ptr<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(aCurve2);
+ anEllipse->distance(aLine, aP1, aP2);
+ }
+ else if (aCurve2->type() == ENTITY_ARC || aCurve2->type() == ENTITY_CIRCLE) {
+ std::shared_ptr<GeomAPI_Circ2d> aCircle = PlaneGCSSolver_Tools::circle(aCurve2);
+ anEllipse->distance(aCircle, aP1, aP2);
+ }
+ else if (aCurve2->type() == ENTITY_ELLIPSE || aCurve2->type() == ENTITY_ELLIPTIC_ARC) {
+ std::shared_ptr<GeomAPI_Ellipse2d> anEl2 = PlaneGCSSolver_Tools::ellipse(aCurve2);
+ anEllipse->distance(anEl2, aP1, aP2);
+ }
+
+ if (aP1 && aP2) {
+ *theIntersectionPoint->x = 0.5 * (aP1->x() + aP2->x());
+ *theIntersectionPoint->y = 0.5 * (aP1->y() + aP2->y());
+ }
+}
--- /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 SketchSolver_ConstraintPerpendicular_H_
+#define SketchSolver_ConstraintPerpendicular_H_
+
+#include <SketchSolver_Constraint.h>
+
+/** \class SketchSolver_ConstraintPerpendicular
+ * \ingroup Plugins
+ * \brief Convert perpendicularity constraint to SolveSpace structure
+ */
+class SketchSolver_ConstraintPerpendicular : public SketchSolver_Constraint
+{
+public:
+ /// Constructor based on SketchPlugin constraint
+ SketchSolver_ConstraintPerpendicular(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint),
+ myCurveCurveAngle(0.0)
+ {}
+
+ /// \brief Notify this object about the feature is changed somewhere
+ virtual void notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update* theUpdater);
+
+protected:
+ /// \brief Converts SketchPlugin constraint to a list of solver constraints
+ virtual void process();
+
+ /// \brief Remove current constraint from the storage and build is again
+ void rebuild();
+
+private:
+ double myCurveCurveAngle;
+ AttributePtr mySharedPoint;
+ EntityWrapperPtr myAuxPoint;
+};
+
+#endif
#include <PlaneGCSSolver_EdgeWrapper.h>
#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_Storage.h>
#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <GeomAPI_Circ2d.h>
+#include <GeomAPI_Lin2d.h>
#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_Ellipse2d.h>
+
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+#include <SketchPlugin_ConstraintMiddle.h>
#include <cmath>
static std::set<AttributePtr> coincidentBoundaryPoints(FeaturePtr theFeature1,
FeaturePtr theFeature2);
+/// \brief Collect points coincident with each of two features
+static std::set<AttributePtr> coincidentPoints(FeaturePtr theFeature1, FeaturePtr theFeature2);
+
/// \brief Check if two connected arcs have centers
/// in same direction relatively to connection point
static bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
double* theAngle = 0);
static ConstraintWrapperPtr
- createArcArcTangency(EntityWrapperPtr theEntity1,
- EntityWrapperPtr theEntity2,
- bool theInternalTangency,
- EntityWrapperPtr theSharedPoint = EntityWrapperPtr(),
- double* theAngle = 0);
+ createCurveCurveTangency(EntityWrapperPtr theEntity1,
+ EntityWrapperPtr theEntity2,
+ bool theInternalTangency,
+ EntityWrapperPtr theSharedPoint = EntityWrapperPtr(),
+ double* theAngle = 0);
+
+static void calculateTangencyPoint(EntityWrapperPtr theCurve1, EntityWrapperPtr theCurve2,
+ GCSPointPtr& theTangencyPoint);
void SketchSolver_ConstraintTangent::process()
if (mySolverConstraint)
myStorage->removeConstraint(myBaseConstraint);
+ std::shared_ptr<PlaneGCSSolver_Storage> aStorage =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(myStorage);
+
mySolverConstraint = ConstraintWrapperPtr();
mySharedPoint = AttributePtr();
+ if (myAuxPoint) {
+ GCS::SET_pD aParams = PlaneGCSSolver_Tools::parameters(myAuxPoint);
+ aStorage->removeParameters(aParams);
+ myAuxPoint = EntityWrapperPtr();
+ }
// Check the quantity of entities of each type and their order (arcs first)
int aNbLines = 0;
int aNbCircles = 0;
+ int aNbEllipses = 0;
std::list<EntityWrapperPtr>::iterator anEntIt = myAttributes.begin();
for (; anEntIt != myAttributes.end(); ++anEntIt) {
if (!(*anEntIt).get())
++aNbLines;
else if ((*anEntIt)->type() == ENTITY_ARC || (*anEntIt)->type() == ENTITY_CIRCLE)
++aNbCircles;
+ else if ((*anEntIt)->type() == ENTITY_ELLIPSE || (*anEntIt)->type() == ENTITY_ELLIPTIC_ARC)
+ ++aNbEllipses;
}
- if (aNbCircles < 1) {
+ if (aNbCircles + aNbEllipses < 1) {
myErrorMsg = SketchSolver_Error::INCORRECT_TANGENCY_ATTRIBUTE();
return;
}
if (aNbLines == 1 && aNbCircles == 1) {
myType = CONSTRAINT_TANGENT_CIRCLE_LINE;
}
- else if (aNbCircles == 2) {
- myType = CONSTRAINT_TANGENT_CIRCLE_CIRCLE;
+ else if (aNbLines + aNbCircles + aNbEllipses == 2) {
+ myType = CONSTRAINT_TANGENT_CURVE_CURVE;
isArcArcInternal = isArcArcTangencyInternal(myAttributes.front(), myAttributes.back());
}
else {
return;
}
+ // Try to find non-boundary points coincident with both features.
+ // It is necesasry to create tangency with ellipse
+ if (aCoincidentPoints.empty() && aNbEllipses > 0)
+ aCoincidentPoints = coincidentPoints(aFeature1, aFeature2);
+
EntityWrapperPtr aSharedPointEntity;
+ std::list<GCSConstraintPtr> anAuxConstraints;
if (!aCoincidentPoints.empty()) {
mySharedPoint = *aCoincidentPoints.begin();
aSharedPointEntity = myStorage->entity(mySharedPoint);
}
+ else if (aNbEllipses > 0) {
+ // create auxiliary point
+ GCSPointPtr aPoint(new GCS::Point);
+ aPoint->x = aStorage->createParameter();
+ aPoint->y = aStorage->createParameter();
+ calculateTangencyPoint(myAttributes.front(), myAttributes.back(), aPoint);
+
+ myAuxPoint.reset(new PlaneGCSSolver_PointWrapper(aPoint));
+ aSharedPointEntity = myAuxPoint;
+
+ // create auxiliary coincident constraints for tangency with ellipse
+ EntityWrapperPtr aDummy;
+ ConstraintWrapperPtr aCoincidence = PlaneGCSSolver_Tools::createConstraint(ConstraintPtr(),
+ CONSTRAINT_PT_ON_CURVE, aDummy, aSharedPointEntity, aDummy, myAttributes.front(), aDummy);
+ anAuxConstraints = aCoincidence->constraints();
+ aCoincidence = PlaneGCSSolver_Tools::createConstraint(ConstraintPtr(),
+ CONSTRAINT_PT_ON_CURVE, aDummy, aSharedPointEntity, aDummy, myAttributes.back(), aDummy);
+ anAuxConstraints.insert(anAuxConstraints.end(),
+ aCoincidence->constraints().begin(), aCoincidence->constraints().end());
+ }
if (myType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
mySolverConstraint = createArcLineTangency(myAttributes.front(), myAttributes.back(),
aSharedPointEntity, &myCurveCurveAngle);
} else {
- mySolverConstraint = createArcArcTangency(myAttributes.front(), myAttributes.back(),
+ mySolverConstraint = createCurveCurveTangency(myAttributes.front(), myAttributes.back(),
isArcArcInternal, aSharedPointEntity, &myCurveCurveAngle);
}
+ if (!anAuxConstraints.empty()) {
+ anAuxConstraints.insert(anAuxConstraints.end(), mySolverConstraint->constraints().begin(),
+ mySolverConstraint->constraints().end());
+ mySolverConstraint->setConstraints(anAuxConstraints);
+ }
+
myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
}
void SketchSolver_ConstraintTangent::adjustConstraint()
{
- if (myType == CONSTRAINT_TANGENT_CIRCLE_CIRCLE) {
+ if (myType == CONSTRAINT_TANGENT_CURVE_CURVE) {
EntityWrapperPtr anEntity1 =
myStorage->entity(myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
EntityWrapperPtr anEntity2 =
}
}
- if (mySharedPoint && !isRebuild) {
- // The features are tangent in the shared point, but the coincidence has been removed/updated.
- // Check if the coincidence is the same.
- std::set<AttributePtr> aCoincidentPoints = coincidentBoundaryPoints(aTgFeat1, aTgFeat2);
- isRebuild = true;
- std::set<AttributePtr>::iterator anIt = aCoincidentPoints.begin();
- for (; anIt != aCoincidentPoints.end() && isRebuild; ++anIt)
- if (*anIt == mySharedPoint)
- isRebuild = false; // the coincidence is still exists => nothing to change
+ if (!isRebuild) {
+ if (mySharedPoint) {
+ // The features are tangent in the shared point, but the coincidence has been removed/updated.
+ // Check if the coincidence is the same.
+ std::set<AttributePtr> aCoincidentPoints = coincidentBoundaryPoints(aTgFeat1, aTgFeat2);
+ isRebuild = true;
+ std::set<AttributePtr>::iterator anIt = aCoincidentPoints.begin();
+ for (; anIt != aCoincidentPoints.end() && isRebuild; ++anIt)
+ if (*anIt == mySharedPoint)
+ isRebuild = false; // the coincidence is still exists => nothing to change
+ }
+ else {
+ // check both features have a coincident point
+ std::set<AttributePtr> aCoincidentPoints = coincidentPoints(aTgFeat1, aTgFeat2);
+ isRebuild = (bool)(myAuxPoint.get()) == (!aCoincidentPoints.empty());
+ }
}
if (isRebuild)
return aCoincidentPoints;
}
+static std::set<AttributePtr> refsToFeatureAndResults(FeaturePtr theFeature)
+{
+ std::set<AttributePtr> aRefs = theFeature->data()->refsToMe();
+ const std::list<ResultPtr>& aResults = theFeature->results();
+ for (std::list<ResultPtr>::const_iterator anIt = aResults.begin();
+ anIt != aResults.end(); ++anIt) {
+ const std::set<AttributePtr>& aResRefs = (*anIt)->data()->refsToMe();
+ aRefs.insert(aResRefs.begin(), aResRefs.end());
+ }
+ return aRefs;
+}
+
+// collect all points coincident with the feature
+static std::set<AttributePtr> pointsOnFeature(FeaturePtr theFeature)
+{
+ std::set<AttributePtr> aPoints;
+
+ std::set<AttributePtr> aRefs = refsToFeatureAndResults(theFeature);
+ for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) {
+ FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aRef && (aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+ aRef->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID() ||
+ aRef->getKind() == SketchPlugin_ConstraintMiddle::ID())) {
+ for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
+ AttributeRefAttrPtr aRefAttr = aRef->refattr(SketchPlugin_Constraint::ATTRIBUTE(i));
+ if (aRefAttr) {
+ AttributePtr anAttr = aRefAttr->attr();
+ if (anAttr && anAttr->id() != SketchPlugin_Arc::CENTER_ID() &&
+ anAttr->id() != SketchPlugin_Circle::CENTER_ID())
+ aPoints.insert(anAttr);
+ }
+ }
+ }
+ }
+ return aPoints;
+}
+
+std::set<AttributePtr> coincidentPoints(FeaturePtr theFeature1, FeaturePtr theFeature2)
+{
+ std::set<AttributePtr> aPointsOnF1 = pointsOnFeature(theFeature1);
+ std::set<AttributePtr> aPointsOnF2 = pointsOnFeature(theFeature2);
+
+ std::set<AttributePtr> aCommonPoints;
+ for (std::set<AttributePtr>::iterator anIt = aPointsOnF1.begin();
+ anIt != aPointsOnF1.end(); ++anIt)
+ if (aPointsOnF2.find(*anIt) != aPointsOnF2.end())
+ aCommonPoints.insert(*anIt);
+ return aCommonPoints;
+}
+
bool isArcArcTangencyInternal(EntityWrapperPtr theArc1, EntityWrapperPtr theArc2)
{
std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(
new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_TANGENT_CIRCLE_LINE));
}
-ConstraintWrapperPtr createArcArcTangency(EntityWrapperPtr theEntity1,
- EntityWrapperPtr theEntity2,
- bool theInternalTangency,
- EntityWrapperPtr theSharedPoint,
- double* theAngle)
+ConstraintWrapperPtr createCurveCurveTangency(EntityWrapperPtr theEntity1,
+ EntityWrapperPtr theEntity2,
+ bool theInternalTangency,
+ EntityWrapperPtr theSharedPoint,
+ double* theAngle)
{
- std::shared_ptr<GCS::Circle> aCirc1 =
- std::dynamic_pointer_cast<GCS::Circle>(GCS_EDGE_WRAPPER(theEntity1)->entity());
- std::shared_ptr<GCS::Circle> aCirc2 =
- std::dynamic_pointer_cast<GCS::Circle>(GCS_EDGE_WRAPPER(theEntity2)->entity());
+ GCSCurvePtr aCurve1 =
+ std::dynamic_pointer_cast<GCS::Curve>(GCS_EDGE_WRAPPER(theEntity1)->entity());
+ GCSCurvePtr aCurve2 =
+ std::dynamic_pointer_cast<GCS::Curve>(GCS_EDGE_WRAPPER(theEntity2)->entity());
GCSConstraintPtr aNewConstr;
if (theSharedPoint) {
GCSPointPtr aPoint =
std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSharedPoint)->point();
- adjustAngleBetweenCurves(aCirc1, aCirc2, aPoint, theAngle);
+ adjustAngleBetweenCurves(aCurve1, aCurve2, aPoint, theAngle);
aNewConstr =
- GCSConstraintPtr(new GCS::ConstraintAngleViaPoint(*aCirc1, *aCirc2, *aPoint, theAngle));
+ GCSConstraintPtr(new GCS::ConstraintAngleViaPoint(*aCurve1, *aCurve2, *aPoint, theAngle));
} else {
+ std::shared_ptr<GCS::Circle> aCirc1 = std::dynamic_pointer_cast<GCS::Circle>(aCurve1);
+ std::shared_ptr<GCS::Circle> aCirc2 = std::dynamic_pointer_cast<GCS::Circle>(aCurve2);
aNewConstr = GCSConstraintPtr(new GCS::ConstraintTangentCircumf(aCirc1->center, aCirc2->center,
aCirc1->rad, aCirc2->rad, theInternalTangency));
}
return ConstraintWrapperPtr(
- new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_TANGENT_CIRCLE_CIRCLE));
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_TANGENT_CURVE_CURVE));
+}
+
+void calculateTangencyPoint(EntityWrapperPtr theCurve1, EntityWrapperPtr theCurve2,
+ GCSPointPtr& theTangencyPoint)
+{
+ std::shared_ptr<GeomAPI_Ellipse2d> anEllipse = PlaneGCSSolver_Tools::ellipse(theCurve1);
+ EntityWrapperPtr aCurve2 = theCurve2;
+ if (!anEllipse) {
+ // try converting to ellipse the second curve
+ anEllipse = PlaneGCSSolver_Tools::ellipse(theCurve2);
+ if (!anEllipse)
+ return; // no one curve is ellipse
+ aCurve2 = theCurve1;
+ }
+
+ GeomPnt2dPtr aP1, aP2;
+ if (aCurve2->type() == ENTITY_LINE) {
+ std::shared_ptr<GeomAPI_Lin2d> aLine = PlaneGCSSolver_Tools::line(aCurve2);
+ anEllipse->distance(aLine, aP1, aP2);
+ }
+ else if (aCurve2->type() == ENTITY_ARC || aCurve2->type() == ENTITY_CIRCLE) {
+ std::shared_ptr<GeomAPI_Circ2d> aCircle = PlaneGCSSolver_Tools::circle(aCurve2);
+ anEllipse->distance(aCircle, aP1, aP2);
+ }
+ else if (aCurve2->type() == ENTITY_ELLIPSE || aCurve2->type() == ENTITY_ELLIPTIC_ARC) {
+ std::shared_ptr<GeomAPI_Ellipse2d> anEl2 = PlaneGCSSolver_Tools::ellipse(aCurve2);
+ anEllipse->distance(anEl2, aP1, aP2);
+ }
+
+ if (aP1 && aP2) {
+ *theTangencyPoint->x = 0.5 * (aP1->x() + aP2->x());
+ *theTangencyPoint->y = 0.5 * (aP1->y() + aP2->y());
+ }
}
bool isArcArcInternal;
double myCurveCurveAngle;
AttributePtr mySharedPoint;
+ EntityWrapperPtr myAuxPoint;
};
#endif
/// Crash in SolveSpace
inline static const std::string& SOLVESPACE_CRASH()
{
- static const std::string MY_ERROR_VALUE("Caution: SolveSpace crash! Constraints are wrong");
+ static const std::string MY_ERROR_VALUE("Caution: SolveSpace crashed! Constraints are wrong");
return MY_ERROR_VALUE;
}
/// Constraint has wrong type
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
+#include <Config_Translator.h>
+
static void sendMessage(const char* theMessageName)
{
SolverConstraintPtr(aConstraint)->process(theStorage, theEventsBlocked);
if (aConstraint->error().empty()) {
aConstraint->startPoint(theFrom);
+ theStorage->adjustParametrizationOfArcs();
theSketchSolver->initialize();
aConstraint->moveTo(theTo);
theStorage->setNeedToResolve(true);
PlaneGCSSolver_Solver::SolveStatus aResult = PlaneGCSSolver_Solver::STATUS_OK;
try {
- if (!isGroupEmpty)
+ if (!isGroupEmpty) {
+ myStorage->adjustParametrizationOfArcs();
aResult = mySketchSolver->solve();
+ }
if (aResult == PlaneGCSSolver_Solver::STATUS_FAILED &&
!myTempConstraints.empty()) {
mySketchSolver->undo();
// ============================================================================
void SketchSolver_Group::computeDoF()
{
- std::ostringstream aDoFMsg;
+ std::string aDoFMsg;
+ static const std::string aMsgContext("Sketch");
int aDoF = mySketchSolver->dof();
/// "DoF = 0" content of string value is used in PartSet by Sketch edit
/// If it is changed, it should be corrected also there
- if (aDoF == 0)
- aDoFMsg << "Sketch is fully fixed (DoF = 0)";
- else
- aDoFMsg << "DoF (degrees of freedom) = " << aDoF;
- mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aDoFMsg.str());
+ //if (aDoF == 0) {
+ // static const std::string aMsgDoF("Sketch is fully fixed (DoF = 0)");
+ // aDoFMsg = Config_Translator::translate(aMsgContext, aMsgDoF);
+ //} else {
+ // static const std::string aMsgDoF("DoF (degrees of freedom) = %1");
+ // Events_InfoMessage aMsg(aMsgContext, aMsgDoF);
+ // aMsg.addParameter(aDoF);
+ // aDoFMsg = Config_Translator::translate(aMsg);
+ //}
+ //// store Unicode value for translated message about DoF
+ //size_t aLen = aDoFMsg.size();
+ //std::wstring aWStr(aLen, L'#');
+ //mbstowcs(&aWStr[0], aDoFMsg.c_str(), aLen);
+ //mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aWStr);
+
+ std::ostringstream aStr;
+ aStr << aDoF;
+ mySketch->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aStr.str());
if (aDoF > 0 && myDOF <= 0)
sendMessage(EVENT_SKETCH_UNDER_CONSTRAINED, mySketch, aDoF);
/// \brief Notify all subscribers about update of the feature
void notify(const FeaturePtr& theFeature) const;
+ /// \brief Make parametrization of arcs consistent.
+ /// Forward arcs should have the last parameter greater than the first parameter.
+ /// Reversed arcs should have the last parameter lesser than the first parameter.
+ virtual void adjustParametrizationOfArcs() = 0;
+
protected:
/// \brief Convert result to feature or attribute if theResult is linked to center of circle/arc
static void resultToFeatureOrAttribute(const ObjectPtr& theResult,
<translation>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.</translation>
</message>
<message>
- <source>Caution: SolveSpace crash! Constraints are wrong</source>
- <translation>Caution: SolveSpace crash! Constraints are wrong</translation>
+ <source>Caution: SolveSpace crashed! Constraints are wrong</source>
+ <translation>Caution: SolveSpace crashed! Constraints are wrong</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>
--- /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>
const std::shared_ptr<GeomAPI_Ax3>& thePlane,
gp_Pnt& thePnt1, gp_Pnt& thePnt2)
{
+ if (!thePlane)
+ return false;
+
DataPtr aData = theConstraint->data();
if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
// The constraint is length
#include <GeomAPI_Curve.h>
#include <GeomAPI_Edge.h>
#include <GeomAPI_Lin.h>
+#include <GeomAPI_Vertex.h>
IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_Perpendicular, SketcherPrs_SymbolPrs);
GeomEdgePtr aEdge1(new GeomAPI_Edge(aShp1));
GeomEdgePtr aEdge2(new GeomAPI_Edge(aShp2));
- std::shared_ptr<GeomAPI_Lin> aLin1 = aEdge1->line();
- std::shared_ptr<GeomAPI_Lin> aLin2 = aEdge2->line();
-
- std::shared_ptr<GeomAPI_Pnt> aPnt = aLin1->intersect(aLin2);
- double aParam1 = aLin1->projParam(aPnt);
- double aParam2 = aLin2->projParam(aPnt);
-
- GeomAPI_Curve aCurve1(aShp1);
- GeomAPI_Curve aCurve2(aShp2);
- bool isInside1 = (aParam1 >= (aCurve1.startParam() - Precision::Confusion())) &&
- (aParam1 <= (aCurve1.endParam() + Precision::Confusion()));
- bool isInside2 = (aParam2 >= (aCurve2.startParam() - Precision::Confusion())) &&
- (aParam2 <= (aCurve2.endParam() + Precision::Confusion()));
-
- if (!(isInside1 && isInside2))
- aPnt = std::shared_ptr<GeomAPI_Pnt>();
+ GeomShapePtr anInter = aEdge1->intersect(aEdge2);
+ std::shared_ptr<GeomAPI_Pnt> aPnt;
+ if (anInter && anInter->isVertex())
+ aPnt = anInter->vertex()->point();
// Compute position of symbols
SketcherPrs_PositionMgr* aMgr = SketcherPrs_PositionMgr::get();
void SketcherPrs_Perpendicular::drawLines(const Handle(Prs3d_Presentation)& thePrs,
Quantity_Color theColor) const
{
- Handle(Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup(thePrs);
-
- Handle(Graphic3d_AspectLine3d) aLineAspect =
- new Graphic3d_AspectLine3d(theColor, Aspect_TOL_SOLID, 2);
- aGroup->SetPrimitivesAspect(aLineAspect);
-
// Draw constrained lines
- addLine(aGroup, SketchPlugin_Constraint::ENTITY_A());
- addLine(aGroup, SketchPlugin_Constraint::ENTITY_B());
+ for (int i = 0; i < 2; ++i) {
+ ObjectPtr anObj =
+ SketcherPrs_Tools::getResult(myConstraint, SketchPlugin_Constraint::ATTRIBUTE(i));
+ GeomShapePtr aShape = SketcherPrs_Tools::getShape(anObj);
+ if (!aShape)
+ return;
+ drawShape(aShape, thePrs, theColor);
+ }
}
-
#include "SketcherPrs_PositionMgr.h"
#include "SketcherPrs_Tools.h"
-#include <GeomAPI_Edge.h>
-#include <GeomAPI_Curve.h>
-#include <GeomAPI_Vertex.h>
-#include <GeomAPI_Dir.h>
#include <GeomAPI_Ax3.h>
#include <GeomAPI_Circ.h>
+#include <GeomAPI_Curve.h>
+#include <GeomAPI_Edge.h>
+#include <GeomAPI_Ellipse.h>
+#include <GeomAPI_Dir.h>
#include <GeomAPI_Lin2d.h>
+#include <GeomAPI_Vertex.h>
#include <GeomDataAPI_Point2D.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_Line.h>
#include <SketchPlugin_ConstraintPerpendicular.h>
+#include <SketchPlugin_ConstraintTangent.h>
#include <TopoDS_Vertex.hxx>
#include <Geom_Curve.hxx>
std::shared_ptr<GeomAPI_Curve> aCurve =
std::shared_ptr<GeomAPI_Curve>(new GeomAPI_Curve(aShape));
- if (aCurve->isCircle()) {
+ if (aCurve->isCircle() || aCurve->isEllipse()) {
Handle(Geom_Curve) aCurv = aCurve->impl<Handle_Geom_Curve>();
GeomAPI_ProjectPointOnCurve anExtr(theP, aCurv);
double aParam = anExtr.LowerDistanceParameter();
if (aDist <= Precision::Confusion())
aList.push_back(aFeature->firstResult());
}
- } else if ((aFeature->getKind() == SketchPlugin_Circle::ID()) ||
- (aFeature->getKind() == SketchPlugin_Arc::ID())) {
+ } else {
GeomCurvePtr aCurve;
ObjectPtr aResObj;
std::list<ResultPtr> aResults = aFeature->results();
}
}
if (aCurve.get()) {
- double aStart = aCurve->startParam();
- double aEnd = aCurve->endParam();
- GeomCirclePtr aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurve));
- GeomPointPtr aProjPnt = aCircle->project(thePnt);
+ GeomPointPtr aProjPnt;
+ if (aFeature->getKind() == SketchPlugin_Circle::ID() ||
+ aFeature->getKind() == SketchPlugin_Arc::ID()) {
+ GeomCirclePtr aCircle = GeomCirclePtr(new GeomAPI_Circ(aCurve));
+ aProjPnt = aCircle->project(thePnt);
+ }
+ else if (aFeature->getKind() == SketchPlugin_Ellipse::ID()) {
+ GeomEllipsePtr anEllipse = GeomEllipsePtr(new GeomAPI_Ellipse(aCurve));
+ aProjPnt = anEllipse->project(thePnt);
+ }
if (aProjPnt && thePnt->distance(aProjPnt) <= Precision::Confusion())
aList.push_back(aResObj);
}
${TEXT_RESOURCES}
OPTIONS -extensions cpp -no-recursive
)
-ELSE(${UPDATE_TRANSLATION)
- QT5_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
-ENDIF(${UPDATE_TRANSLATION)
+ELSE(${UPDATE_TRANSLATION})
+ 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})
case Accept:
case AcceptAll: {
aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_ok.png"),
- "Apply" /*empty to show error*/, aParent);
+ tr("Apply"), aParent);
}
break;
case AcceptPlus: {
aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_ok-plus.png"),
- "Apply and continue" /*empty to show error*/, aParent);
+ tr("Apply and continue"), aParent);
}
break;
case Abort:
case AbortAll: {
- aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_cancel.png"), "Cancel",
+ aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_cancel.png"), tr("Cancel"),
aParent);
}
break;
case Help: {
- aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_help.png"), "Help",
+ aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_help.png"), tr("Help"),
aParent);
}
break;
case Preview: {
aResult = ModuleBase_Tools::createAction(QIcon(), tr("See preview"),
- aParent, 0, 0, "Compute preview");
+ aParent, 0, 0, tr("Compute preview"));
aResult->setStatusTip(aResult->toolTip());
}
break;
bool hasCompositeOwner = false;
bool hasResultInHistory = false;
bool hasFolder = false;
- bool canBeDeleted = true;
ModuleBase_Tools::checkObjects(aObjects, hasResult, hasFeature, hasParameter,
hasCompositeOwner, hasResultInHistory, hasFolder);
//Process Feature
if( aMgr->activeDocument() == aObject->document() )
{
action("RENAME_CMD")->setEnabled(true);
- if (aObject->groupName() == ModelAPI_ResultConstruction::group()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
- canBeDeleted = aFeature->isInHistory();
- action("DELETE_CMD")->setEnabled(canBeDeleted);
- }
- else
- action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
+ action("DELETE_CMD")->setEnabled(!hasCompositeOwner);
action("CLEAN_HISTORY_CMD")->setEnabled(!hasCompositeOwner &&
(hasFeature || hasParameter));
}
action("SHOW_ONLY_CMD")->setEnabled(true);
action("SHADING_CMD")->setEnabled(true);
action("WIREFRAME_CMD")->setEnabled(true);
-
- foreach(ObjectPtr aObj, aObjects) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
- if (!aFeature->isInHistory()) {
- canBeDeleted = false;
- break;
- }
- }
- action("DELETE_CMD")->setEnabled(canBeDeleted);
}
+ if (hasFeature && myWorkshop->canMoveFeature())
+ action("MOVE_CMD")->setEnabled(true);
} // end multi-selection
// Check folder management commands state if only features are selected
break;
}
if (!hasCompositeOwner && allActive ) {
- if (hasResult || hasFeature || hasParameter) // #2924 results can be erased
- action("DELETE_CMD")->setEnabled(canBeDeleted);
+ if (hasResult || hasFeature || hasParameter) // #2924 results can be erased
+ action("DELETE_CMD")->setEnabled(true);
}
if (!hasCompositeOwner && allActive && (hasFeature|| hasParameter))
action("CLEAN_HISTORY_CMD")->setEnabled(true);
if (myWorkshop->canChangeProperty("TRANSPARENCY_CMD"))
action("TRANSPARENCY_CMD")->setEnabled(true);
- // Delete command is not used in viewer pop-up menu
- action("DELETE_CMD")->setEnabled(false);
+ action("DELETE_CMD")->setEnabled(true);
}
void XGUI_ContextMenuMgr::connectObjectBrowser()
aActions.append(action("ADD_OUT_FOLDER_BEFORE_CMD"));
aActions.append(action("ADD_OUT_FOLDER_AFTER_CMD"));
aActions.append(mySeparator3);
- //aActions.append(action("MOVE_CMD"));
+ aActions.append(action("MOVE_CMD"));
aActions.append(action("COLOR_CMD"));
aActions.append(action("DEFLECTION_CMD"));
aActions.append(action("TRANSPARENCY_CMD"));
return aWasEnabled;
}
-//**************************************************************
-bool XGUI_Displayer::isUpdateEnabled() const
-{
- return myViewerBlockedRecursiveCount == 0;
-}
-
//**************************************************************
void XGUI_Displayer::updateViewer() const
{
if (getCallBack()) getCallBack()->Remove(aTrihedron);
#endif
}
-
- updateViewer();
}
//**************************************************************
bool enableUpdateViewer(const bool isEnabled);
/// Returns true if the viewer update is not blocked
- bool isUpdateEnabled() const;
+ bool isUpdateEnabled() const
+ {
+ return myViewerBlockedRecursiveCount == 0;
+ }
/// Updates the viewer
void updateViewer() const;
if (aLabel) continue;
// Get the original tool tip of the widget
- QString aTTip = aWidget->toolTip().section("Errors:\n", 0, 0).trimmed();
+ QString aTTip = aWidget->toolTip().section(tr("Errors:") + "\n", 0, 0).trimmed();
// Add the error message into the tool tip
if (!theError.isEmpty()) {
if (!aTTip.isEmpty())
aTTip.append('\n');
- aTTip += "Errors:\n" + theError;
+ aTTip += tr("Errors:") + "\n" + theError;
}
aWidget->setToolTip(aTTip);
//aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
mySubShapesTab->setHorizontalHeaderLabels(aTitles);
QStringList aSubShapes;
- aSubShapes << "SHAPE" << "COMPOUND" << "COMPSOLID" <<
- "SOLID" << "SHELL" << "FACE" << "WIRE" << "EDGE" << "VERTEX";
+ aSubShapes << tr("SHAPE") << tr("COMPOUND") << tr("COMPSOLID") <<
+ tr("SOLID") << tr("SHELL") << tr("FACE") << tr("WIRE") << tr("EDGE") << tr("VERTEX");
int i = 0;
foreach(QString aType, aSubShapes) {
QTableWidgetItem* aItem = new QTableWidgetItem(aType);
#endif
#include <ModuleBase_IModule.h>
+#include <ModuleBase_Tools.h>
#include <QObject>
#include <QAction>
#endif
return;
}
+ QString aWchName = ModuleBase_Tools::translate("workshop", theMessage->workbenchId());
+ theMessage->setToolBarId(ModuleBase_Tools::translate("workshop",
+ theMessage->workbenchId()).toStdString());
#ifdef HAVE_SALOME
- std::shared_ptr<XGUI_MenuWorkbench> aWorkbench = findWorkbench(theMessage->workbenchId());
+ std::string aWchNameString = aWchName.toStdString();
+ std::shared_ptr<XGUI_MenuWorkbench> aWorkbench = findWorkbench(aWchNameString);
std::shared_ptr<XGUI_MenuGroup> aGroup = aWorkbench->findGroup(theMessage->groupId());
aGroup->setFeatureInfo(theMessage);
#else
ActionInfo aFeatureInfo;
aFeatureInfo.initFrom(theMessage);
- QString aWchName = QString::fromStdString(theMessage->workbenchId());
QStringList aNestedFeatures =
QString::fromStdString(theMessage->nestedFeatures()).split(" ", QString::SkipEmptyParts);
QList<QAction*> aNestedActList;
aContext->HilightNextDetected(aView);
else if ((theEvent->key() == Qt::Key_P))
aContext->HilightPreviousDetected(aView);
- //aViewer->updateHighlight();
+ aViewer->updateHighlight();
isAccepted = true;
}
}
eachWidget->restoreValue();
}
// the repaint is used here to immediately react in GUI to the values change.
- repaint();
+ update();
}
void XGUI_PropertyPanel::createContentPanel(FeaturePtr theFeature)
void XGUI_SelectionActivate::deactivateTrihedronInSelectionModes()
{
Handle(AIS_InteractiveContext) aContext = AISContext();
- Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(getTrihedron());
- /// deactivate trihedron in selection modes
- TColStd_ListOfInteger aTColModes;
- aContext->ActivatedModes(aTrihedron, aTColModes);
- TColStd_ListIteratorOfListOfInteger itr( aTColModes );
- for (; itr.More(); itr.Next() ) {
- Standard_Integer aMode = itr.Value();
- aContext->Deactivate(aTrihedron, aMode);
+ if (!aContext.IsNull()) {
+ Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(getTrihedron());
+ /// deactivate trihedron in selection modes
+ TColStd_ListOfInteger aTColModes;
+ aContext->ActivatedModes(aTrihedron, aTColModes);
+ TColStd_ListIteratorOfListOfInteger itr(aTColModes);
+ for (; itr.More(); itr.Next()) {
+ Standard_Integer aMode = itr.Value();
+ aContext->Deactivate(aTrihedron, aMode);
+ }
}
}
}
}
-void XGUI_ViewerProxy::eraseHighlight()
+bool XGUI_ViewerProxy::eraseHighlight()
{
Handle(AIS_InteractiveContext) aContext = AISContext();
Handle(AIS_InteractiveObject) anAISIO;
AIS_ListIteratorOfListOfInteractive aLIt;
+ bool isErased = myHighlights.Extent() > 0;
for (aLIt.Initialize(myHighlights); aLIt.More(); aLIt.Next()) {
anAISIO = aLIt.Value();
aContext->Remove(anAISIO, false);
}
myHighlights.Clear();
+ return isErased;
}
void XGUI_ViewerProxy::updateHighlight()
else {
myResult = ResultPtr();
}
- aContext->UpdateCurrentViewer();
+ update();
}
isDisplayed = aRes.get();
}
}
if (!isDisplayed) {
- eraseHighlight();
- aContext->UpdateCurrentViewer();
+ if (eraseHighlight()) {
+ update();
+ }
myResult = ResultPtr();
}
}
// aView3d->DepthFitAll();
// }
//#endif
-//}
\ No newline at end of file
+//}
+
+
+#ifdef HAVE_SALOME
+void XGUI_ViewerProxy::setFitter(OCCViewer_Fitter* theFitter)
+{
+ myWorkshop->salomeConnector()->viewer()->setFitter(theFitter);
+}
+
+OCCViewer_Fitter* XGUI_ViewerProxy::fitter() const
+{
+ return myWorkshop->salomeConnector()->viewer()->fitter();
+}
+#else
+void XGUI_ViewerProxy::setFitter(AppElements_Fitter* theFitter)
+{
+ myWorkshop->mainWindow()->viewer()->setFitter(theFitter);
+}
+
+AppElements_Fitter* XGUI_ViewerProxy::fitter() const
+{
+ return myWorkshop->mainWindow()->viewer()->fitter();
+}
+#endif
#include <AIS_Trihedron.hxx>
#include <AIS_ListOfInteractive.hxx>
-#ifndef HAVE_SALOME
+#ifdef HAVE_SALOME
+#include <OCCViewer_ViewModel.h>
+#else
+ #include <AppElements_Viewer.h>
#include <AppElements_ViewWindow.h>
#endif
+
+
class XGUI_Workshop;
/**
* \ingroup GUI
// Fit all along Z (perpendicular to display)
//virtual void Zfitall();
+#ifdef HAVE_SALOME
+ virtual void setFitter(OCCViewer_Fitter* theFitter);
+ virtual OCCViewer_Fitter* fitter() const;
+#else
+ virtual void setFitter(AppElements_Fitter* theFitter);
+ virtual AppElements_Fitter* fitter() const;
+#endif
+
signals:
/// Emits by mouse entering the view port
void enterViewPort();
private:
void displayHighlight(FeaturePtr theFeature, const TopoDS_Shape& theIgnoreShape);
- void eraseHighlight();
+ bool eraseHighlight();
XGUI_Workshop* myWorkshop;
// Load translations
QStringList aLangs;
- aLangs << "*_en.ts"; // load by default eng translations
+#ifdef MAKE_TRANSLATION
QString aCurrLang = aResMgr->stringValue("language", "language", "en");
- if(aCurrLang != "en") {
+ if(aCurrLang == "en") {
+ aLangs << "*_en.ts";
+ } else {
aLangs << "*_" + aCurrLang + ".ts"; // then replace with translated files
}
+#else
+ aLangs << "*_en.ts"; // load by default eng translations
+#endif
foreach(QString aLang, aLangs) {
QStringList aFilters;
#ifndef HAVE_SALOME
connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
- onTrihedronVisibilityChanged(true);
+ myDisplayer->displayTrihedron(true);
#endif
connect(myEventsListener, SIGNAL(errorOccurred(std::shared_ptr<Events_InfoMessage>)),
myModule->propertyPanelDefined(theOperation);
#ifndef DEBUG_FEATURE_NAME
- myPropertyPanel->setWindowTitle(theOperation->getDescription()->description());
+ myPropertyPanel->setWindowTitle(ModuleBase_Tools::translate("workshop",
+ theOperation->getDescription()->description().toStdString()));
#else
std::string aFeatureName = aFeature->name();
myPropertyPanel->setWindowTitle(QString("%1: %2")
- .arg(theOperation->getDescription()->description())
- .arg(aFeatureName.c_str()));
+ .arg(translate(theOperation->getDescription()->description()))
+ .arg(translate(aFeatureName.c_str())));
#endif
myErrorMgr->setPropertyPanel(myPropertyPanel);
void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState)
{
XGUI_Displayer* aDisplayer = displayer();
- if (aDisplayer)
+ if (aDisplayer) {
aDisplayer->displayTrihedron(theState);
+ aDisplayer->updateViewer();
+ }
}
//******************************************************
void XGUI_Workshop::onWidgetObjectUpdated()
{
operationMgr()->onValidateOperation();
+ myDisplayer->updateViewer();
}
//******************************************************
if (!(hasResult || hasFeature || hasParameter || hasFolder))
return;
+ // Remove from the list non-deletable objects: infinite constuctions which are not in history
+ bool notDelete = true;
+ QObjectPtrList::iterator aIt;
+ for (aIt = anObjects.begin(); aIt != anObjects.end(); aIt++) {
+ ObjectPtr aObj = (*aIt);
+ ResultConstructionPtr aConstr = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aObj);
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
+ notDelete = (!aFeature->isInHistory()) && aConstr->isInfinite();
+ if (notDelete) {
+ anObjects.removeAll(aObj);
+ aIt--;
+ }
+ }
// delete objects
std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
std::set<FeaturePtr> aFeatures;
operationMgr()->commitOperation();
else
operationMgr()->abortOperation(operationMgr()->currentOperation());
+
+ myDisplayer->updateViewer();
}
//**************************************************************
QString anUnusedNames = aNames.join(", ");
QString anActionId = "CLEAN_HISTORY_CMD";
- QString aDescription = contextMenuMgr()->action(anActionId)->text();
+ QString aDescription = ModuleBase_Tools::translate("workshop",
+ contextMenuMgr()->action(anActionId)->text().toStdString());
QMessageBox aMessageBox(desktop());
aMessageBox.setWindowTitle(aDescription);
}
//**************************************************************
+bool compareFeature(const FeaturePtr& theF1, const FeaturePtr& theF2) {
+ DocumentPtr aDoc = theF1->document();
+ return aDoc->index(theF1) < aDoc->index(theF2);
+}
void XGUI_Workshop::moveObjects()
{
if (!abortAllOperations())
SessionPtr aMgr = ModelAPI_Session::get();
- QString anActionId = "MOVE_CMD";
- QString aDescription = contextMenuMgr()->action(anActionId)->text();
- aMgr->startOperation(aDescription.toStdString());
-
QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
// It is necessary to clear selection in order to avoid selection changed event during
// moving and negative consequences connected with processing of already moved items
if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
return;
+ QString anActionId = "MOVE_CMD";
+ QString aDescription = contextMenuMgr()->action(anActionId)->text();
+ aMgr->startOperation(aDescription.toStdString());
+
+ // Sort features by index in document
+ std::list<FeaturePtr> aFList(aFeatures.begin(), aFeatures.end());
+ aFList.sort(compareFeature);
+
DocumentPtr anActiveDocument = aMgr->activeDocument();
FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
- std::set<FeaturePtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
+ std::list<FeaturePtr>::const_iterator anIt = aFList.begin(), aLast = aFList.end();
for (; anIt != aLast; anIt++) {
FeaturePtr aFeature = *anIt;
if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
aCurrentFeature = anActiveDocument->currentFeature(true);
}
aMgr->finishOperation();
+ updateCommandStatus();
}
//**************************************************************
// 2. show the dialog to change the value
XGUI_PropertyDialog* aDlg = new XGUI_PropertyDialog(desktop());
- aDlg->setWindowTitle("Transparency");
+ aDlg->setWindowTitle(tr("Transparency"));
XGUI_TransparencyWidget* aTransparencyWidget = new XGUI_TransparencyWidget(aDlg);
connect(aTransparencyWidget, SIGNAL(transparencyValueChanged()),
this, SLOT(onTransparencyValueChanged()));
if (aRedisplayed || isCustomized) {
Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_EMPTY_AIS_PRESENTATION));
- aDisplayer->updateViewer();
+ // Do not update viewer here because it can be called in a loop
+ // In this case Update has to be called after redisplay event
+ //aDisplayer->updateViewer();
}
}
<message>
<location filename="XGUI_Tools.cpp" line="154"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Attention</translation>
</message>
<message>
<location filename="XGUI_Tools.cpp" line="213"/>
<source>Name %2 already exists in %1.</source>
- <translation type="unfinished"></translation>
+ <translation>Le nom %2 existe déjà dans %1.</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="170"/>
<source>Move to the end</source>
- <translation type="unfinished"></translation>
+ <translation>Aller à la fin</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="177"/>
<source>SHAPER files (*.shaper *.cadbld)</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers SHAPER (*.shaper *.cadbld)</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="178"/>
<source>SHAPER files (*.shaper)</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers SHAPER (*.shaper)</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="181"/>
<source>CAD Builder files (*.cadbld);;All files (*.*)</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers CAD Builder (*.cadbld);;Tous les fichiers (*. *)</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="182"/>
<source>CAD Builder files (*.cadbld)</source>
- <translation type="unfinished"></translation>
+ <translation>Fichiers CAD Builder (*.cadbld)</translation>
</message>
<message>
<location filename="XGUI_OperationMgr.cpp" line="893"/>
<source>Abort operation</source>
- <translation type="unfinished"></translation>
+ <translation>Abandonner l'opération</translation>
</message>
<message>
<location filename="XGUI_OperationMgr.cpp" line="904"/>
<source>Validate operation</source>
- <translation type="unfinished"></translation>
+ <translation>Valider l'opération</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_ActionsMgr.cpp" line="194"/>
<source>Shortcut %1 is already defined. Ignore.</source>
- <translation type="unfinished"></translation>
+ <translation>Le raccourci %1 est déjà défini. Ignorer.</translation>
+ </message>
+ <message>
+ <location filename="XGUI_ActionsMgr.cpp" line="254"/>
+ <source>Apply</source>
+ <translation>Appliquer</translation>
+ </message>
+ <message>
+ <location filename="XGUI_ActionsMgr.cpp" line="259"/>
+ <source>Apply and continue</source>
+ <translation>Appliquer et continuer</translation>
+ </message>
+ <message>
+ <location filename="XGUI_ActionsMgr.cpp" line="264"/>
+ <source>Cancel</source>
+ <translation>Annuler</translation>
+ </message>
+ <message>
+ <location filename="XGUI_ActionsMgr.cpp" line="269"/>
+ <source>Help</source>
+ <translation>Aide</translation>
</message>
<message>
<location filename="XGUI_ActionsMgr.cpp" line="274"/>
<source>See preview</source>
- <translation type="unfinished"></translation>
+ <translation>Voir l'aperçu</translation>
+ </message>
+ <message>
+ <location filename="XGUI_ActionsMgr.cpp" line="275"/>
+ <source>Compute preview</source>
+ <translation>Calculer l'aperçu avant impression</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_ColorDialog.cpp" line="35"/>
<source>Color</source>
- <translation type="unfinished"></translation>
+ <translation>Couleur</translation>
</message>
<message>
<location filename="XGUI_ColorDialog.cpp" line="53"/>
<source>Random</source>
- <translation type="unfinished"></translation>
+ <translation>Aléatoire</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="88"/>
<source>Delete</source>
- <translation type="unfinished"></translation>
+ <translation>Effacer</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="95"/>
<source>Rename</source>
- <translation type="unfinished"></translation>
+ <translation>Renommer</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="104"/>
<source>Clean history</source>
- <translation type="unfinished"></translation>
+ <translation>Vider l’historique</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="107"/>
<source>Color...</source>
- <translation type="unfinished"></translation>
+ <translation>Couleur...</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="110"/>
<source>Deflection...</source>
- <translation type="unfinished"></translation>
+ <translation>Déviation...</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="114"/>
<source>Transparency...</source>
- <translation type="unfinished"></translation>
+ <translation>Transparence...</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="117"/>
<source>Show</source>
- <translation type="unfinished"></translation>
+ <translation>Afficher</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="120"/>
<source>Show only</source>
- <translation type="unfinished"></translation>
+ <translation>Montrer seulement</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="124"/>
<source>Hide</source>
- <translation type="unfinished"></translation>
+ <translation>Cacher</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="128"/>
<source>Hide all</source>
- <translation type="unfinished"></translation>
+ <translation>Cacher tout</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="132"/>
<source>Shading</source>
- <translation type="unfinished"></translation>
+ <translation>Ombrage</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="135"/>
<source>Wireframe</source>
- <translation type="unfinished"></translation>
+ <translation>Fil de fer</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="148"/>
<source>Vertices</source>
- <translation type="unfinished"></translation>
+ <translation>Sommets</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="153"/>
<source>Edges</source>
- <translation type="unfinished"></translation>
+ <translation>Arêtes</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="158"/>
<source>Faces</source>
- <translation type="unfinished"></translation>
+ <translation>Faces</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="163"/>
<source>Results</source>
- <translation type="unfinished"></translation>
+ <translation>Résultats</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="171"/>
<source>Select results</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionnez les résultats</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="175"/>
<source>Select parent feature</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionner une entité parente</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="179"/>
<source>TInspector</source>
- <translation type="unfinished"></translation>
+ <translation>TInspector</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="185"/>
<source>Insert a folder before</source>
- <translation type="unfinished"></translation>
+ <translation>Insérer un dossier avant</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="189"/>
<source>Move into the previous folder</source>
- <translation type="unfinished"></translation>
+ <translation>Déplacer dans le dossier précédent</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="193"/>
<source>Move into the next folder</source>
- <translation type="unfinished"></translation>
+ <translation>Se déplacer dans le dossier suivant</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="197"/>
<source>Move out before the folder</source>
- <translation type="unfinished"></translation>
+ <translation>Sortir avant le dossier</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="201"/>
<source>Move out after the folder</source>
- <translation type="unfinished"></translation>
+ <translation>Sortir après le dossier</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="205"/>
<source>Set view by inverted normal to face</source>
- <translation type="unfinished"></translation>
+ <translation>Définir la vue par normale inversée à la face</translation>
</message>
<message>
<location filename="XGUI_ContextMenuMgr.cpp" line="209"/>
<source>Set view by normal to face</source>
- <translation type="unfinished"></translation>
+ <translation>Définir la vue par la normale à la face</translation>
</message>
<message>
- <location filename="XGUI_ContextMenuMgr.cpp" line="811"/>
+ <location filename="XGUI_ContextMenuMgr.cpp" line="806"/>
<source>Selection mode</source>
- <translation type="unfinished"></translation>
+ <translation>Mode de sélection</translation>
</message>
<message>
- <location filename="XGUI_ContextMenuMgr.cpp" line="864"/>
+ <location filename="XGUI_ContextMenuMgr.cpp" line="859"/>
<source>Windows</source>
- <translation type="unfinished"></translation>
+ <translation>Fenêtres</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_ObjectsBrowser.cpp" line="203"/>
<source>History change</source>
- <translation type="unfinished"></translation>
+ <translation>Changement l'historique</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_DeflectionDialog.cpp" line="35"/>
<source>Deflection</source>
- <translation type="unfinished"></translation>
+ <translation>Déviation</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_ErrorDialog.cpp" line="37"/>
<source>Application errors</source>
- <translation type="unfinished"></translation>
+ <translation>Erreurs d'application</translation>
+ </message>
+</context>
+<context>
+ <name>XGUI_ErrorMgr</name>
+ <message>
+ <location filename="XGUI_ErrorMgr.cpp" line="204"/>
+ <location filename="XGUI_ErrorMgr.cpp" line="209"/>
+ <source>Errors:</source>
+ <translation>Erreurs:</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_FacesPanel.cpp" line="54"/>
<source>Hide Faces</source>
- <translation type="unfinished"></translation>
+ <translation>Masquer les faces</translation>
</message>
<message>
<location filename="XGUI_FacesPanel.cpp" line="63"/>
<source>Transparent</source>
- <translation type="unfinished"></translation>
+ <translation>Transparent</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="115"/>
<source>Inspection Panel</source>
- <translation type="unfinished"></translation>
+ <translation>Panneau d'inspection</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="125"/>
<source>Object</source>
- <translation type="unfinished"></translation>
+ <translation>Objet</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="137"/>
<source>Sub-shapes</source>
- <translation type="unfinished"></translation>
+ <translation>Sous-formes</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="137"/>
<source>Number</source>
- <translation type="unfinished"></translation>
+ <translation>Nombre</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="141"/>
+ <source>SHAPE</source>
+ <translation>FORME</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="141"/>
+ <source>COMPOUND</source>
+ <translation>ASSEMBLAGE</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="141"/>
+ <source>COMPSOLID</source>
+ <translation>COMPSOLIDE</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="142"/>
+ <source>SOLID</source>
+ <translation>SOLIDE</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="142"/>
+ <source>SHELL</source>
+ <translation>COQUE</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="142"/>
+ <source>FACE</source>
+ <translation>FACE</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="142"/>
+ <source>WIRE</source>
+ <translation>CONTOUR</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="142"/>
+ <source>EDGE</source>
+ <translation>BORD</translation>
+ </message>
+ <message>
+ <location filename="XGUI_InspectionPanel.cpp" line="142"/>
+ <source>VERTEX</source>
+ <translation>SOMMET</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="165"/>
<source>Type:</source>
- <translation type="unfinished"></translation>
+ <translation>Type:</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="340"/>
<source>Vertex</source>
- <translation type="unfinished"></translation>
+ <translation>Sommet</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="343"/>
<source>Coordinates</source>
- <translation type="unfinished"></translation>
+ <translation>Coordonnées</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="352"/>
<source>Degenerated</source>
- <translation type="unfinished"></translation>
+ <translation>Dégénéré</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="359"/>
<source>Line segment</source>
- <translation type="unfinished"></translation>
+ <translation>Segment de ligne</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="371"/>
<location filename="XGUI_InspectionPanel.cpp" line="624"/>
<location filename="XGUI_InspectionPanel.cpp" line="662"/>
<source>Center</source>
- <translation type="unfinished"></translation>
+ <translation>Centre</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="372"/>
<location filename="XGUI_InspectionPanel.cpp" line="458"/>
<location filename="XGUI_InspectionPanel.cpp" line="615"/>
<source>Normal</source>
- <translation type="unfinished"></translation>
+ <translation>Normale</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="373"/>
<location filename="XGUI_InspectionPanel.cpp" line="676"/>
<location filename="XGUI_InspectionPanel.cpp" line="692"/>
<source>Dimensions</source>
- <translation type="unfinished"></translation>
+ <translation>Dimensions</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="374"/>
<location filename="XGUI_InspectionPanel.cpp" line="626"/>
<location filename="XGUI_InspectionPanel.cpp" line="638"/>
<source>Radius</source>
- <translation type="unfinished"></translation>
+ <translation>Rayon</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="388"/>
<location filename="XGUI_InspectionPanel.cpp" line="665"/>
<source>Major radius</source>
- <translation type="unfinished"></translation>
+ <translation>Rayon majeur</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="389"/>
<location filename="XGUI_InspectionPanel.cpp" line="666"/>
<source>Minor radius</source>
- <translation type="unfinished"></translation>
+ <translation>Rayon mineur</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="393"/>
<source>Edge</source>
- <translation type="unfinished"></translation>
+ <translation>Bord</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="398"/>
<source>Start point</source>
- <translation type="unfinished"></translation>
+ <translation>Point de départ</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="399"/>
<source>End point</source>
- <translation type="unfinished"></translation>
+ <translation>Point final</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="408"/>
<source>Closed</source>
- <translation type="unfinished"></translation>
+ <translation>Fermé</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="413"/>
<source>Polygon</source>
- <translation type="unfinished"></translation>
+ <translation>Polygone</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="417"/>
<source>Point</source>
- <translation type="unfinished"></translation>
+ <translation>Point</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="421"/>
<source>Wire</source>
- <translation type="unfinished"></translation>
+ <translation>Contour</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="456"/>
<source>Rectangle</source>
- <translation type="unfinished"></translation>
+ <translation>Rectangle</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="457"/>
<source>Corner</source>
- <translation type="unfinished"></translation>
+ <translation>Coin</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="460"/>
<location filename="XGUI_InspectionPanel.cpp" line="677"/>
<location filename="XGUI_InspectionPanel.cpp" line="693"/>
<source>Width</source>
- <translation type="unfinished"></translation>
+ <translation>Largeur</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="461"/>
<location filename="XGUI_InspectionPanel.cpp" line="679"/>
<location filename="XGUI_InspectionPanel.cpp" line="695"/>
<source>Height</source>
- <translation type="unfinished"></translation>
+ <translation>Hauteur</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="470"/>
<source>Plane</source>
- <translation type="unfinished"></translation>
+ <translation>Plan</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="476"/>
<location filename="XGUI_InspectionPanel.cpp" line="507"/>
<location filename="XGUI_InspectionPanel.cpp" line="547"/>
<source>Sphere</source>
- <translation type="unfinished"></translation>
+ <translation>Sphère</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="481"/>
<location filename="XGUI_InspectionPanel.cpp" line="512"/>
<location filename="XGUI_InspectionPanel.cpp" line="552"/>
<source>Cylinder</source>
- <translation type="unfinished"></translation>
+ <translation>Cylindre</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="486"/>
<location filename="XGUI_InspectionPanel.cpp" line="517"/>
<location filename="XGUI_InspectionPanel.cpp" line="557"/>
<source>Cone</source>
- <translation type="unfinished"></translation>
+ <translation>Cône</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="491"/>
<location filename="XGUI_InspectionPanel.cpp" line="522"/>
<location filename="XGUI_InspectionPanel.cpp" line="562"/>
<source>Torus</source>
- <translation type="unfinished"></translation>
+ <translation>Tore</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="494"/>
<source>Face</source>
- <translation type="unfinished"></translation>
+ <translation>Face</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="528"/>
<location filename="XGUI_InspectionPanel.cpp" line="568"/>
<source>Box</source>
- <translation type="unfinished"></translation>
+ <translation>Boîte</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="530"/>
<location filename="XGUI_InspectionPanel.cpp" line="570"/>
<source>Rotated Box</source>
- <translation type="unfinished"></translation>
+ <translation>Boîte tournée</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="534"/>
<source>Shell</source>
- <translation type="unfinished"></translation>
+ <translation>Coque</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="574"/>
<source>Solid</source>
- <translation type="unfinished"></translation>
+ <translation>Solide</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="604"/>
<source>Bounding box</source>
- <translation type="unfinished"></translation>
+ <translation>Boîte englobante</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="605"/>
<source>Minimal corner</source>
- <translation type="unfinished"></translation>
+ <translation>Coin minimal</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="606"/>
<source>Maximal corner</source>
- <translation type="unfinished"></translation>
+ <translation>Coin maximal</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="614"/>
<source>Origin</source>
- <translation type="unfinished"></translation>
+ <translation>Origine</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="635"/>
<location filename="XGUI_InspectionPanel.cpp" line="675"/>
<location filename="XGUI_InspectionPanel.cpp" line="689"/>
<source>Position</source>
- <translation type="unfinished"></translation>
+ <translation>Position</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="636"/>
<location filename="XGUI_InspectionPanel.cpp" line="649"/>
<location filename="XGUI_InspectionPanel.cpp" line="663"/>
<source>Axis</source>
- <translation type="unfinished"></translation>
+ <translation>Axe</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="651"/>
<source>Radius 1</source>
- <translation type="unfinished"></translation>
+ <translation>Rayon 1</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="652"/>
<source>Radius 2</source>
- <translation type="unfinished"></translation>
+ <translation>Rayon 2</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="678"/>
<location filename="XGUI_InspectionPanel.cpp" line="694"/>
<source>Depth</source>
- <translation type="unfinished"></translation>
+ <translation>Profondeur</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="690"/>
<source>Z axis</source>
- <translation type="unfinished"></translation>
+ <translation>Axe Z</translation>
</message>
<message>
<location filename="XGUI_InspectionPanel.cpp" line="691"/>
<source>X axis</source>
- <translation type="unfinished"></translation>
+ <translation>Axe X</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_ObjectsBrowser.cpp" line="396"/>
<source>Part set</source>
- <translation type="unfinished"></translation>
+ <translation>Ensemble</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_OperationMgr.cpp" line="254"/>
<source>All active operations will be aborted.</source>
- <translation type="unfinished"></translation>
+ <translation>Toutes les opérations actives seront annulées.</translation>
</message>
<message>
<location filename="XGUI_OperationMgr.cpp" line="259"/>
<source>Please validate all your active operations before saving.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez valider toutes vos opérations actives avant de sauvegarder.</translation>
</message>
<message>
<location filename="XGUI_OperationMgr.cpp" line="341"/>
<source>%1 operation will be aborted.</source>
- <translation type="unfinished"></translation>
+ <translation>%1 opération sera abandonnée.</translation>
</message>
<message>
<location filename="XGUI_OperationMgr.cpp" line="348"/>
<source>Please validate your %1 before saving.</source>
- <translation type="unfinished"></translation>
+ <translation>Veuillez valider votre %1 avant de sauvegarder.</translation>
</message>
</context>
<context>
<location filename="XGUI_PropertyPanel.cpp" line="73"/>
<location filename="XGUI_PropertyPanel.cpp" line="167"/>
<source>Property Panel</source>
- <translation type="unfinished"></translation>
+ <translation>Panneau de propriété</translation>
</message>
</context>
<context>
<message>
<location filename="XGUI_TransparencyWidget.cpp" line="39"/>
<source>Opaque</source>
- <translation type="unfinished"></translation>
+ <translation>Opaque</translation>
</message>
<message>
<location filename="XGUI_TransparencyWidget.cpp" line="45"/>
<source>Transparent</source>
- <translation type="unfinished"></translation>
+ <translation>Transparent</translation>
</message>
</context>
<context>
<location filename="XGUI_Workshop.cpp" line="427"/>
<location filename="XGUI_Workshop.cpp" line="489"/>
<source>Undo</source>
- <translation type="unfinished"></translation>
+ <translation>Annuler</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="428"/>
<location filename="XGUI_Workshop.cpp" line="489"/>
<source>Undo last command</source>
- <translation type="unfinished"></translation>
+ <translation>Annuler la dernière commande</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="432"/>
<source>INF_DESK_TOOLBAR_STANDARD</source>
- <translation type="unfinished"></translation>
+ <translation>AA</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="438"/>
<location filename="XGUI_Workshop.cpp" line="498"/>
<source>Redo</source>
- <translation type="unfinished"></translation>
+ <translation>Refaire</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="438"/>
<location filename="XGUI_Workshop.cpp" line="498"/>
<source>Redo last command</source>
- <translation type="unfinished"></translation>
+ <translation>Refaire la dernière commande</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="460"/>
<source>Export native...</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter natif...</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="461"/>
<source>Export the current document into a native file</source>
- <translation type="unfinished"></translation>
+ <translation>Exporter le document actuel dans un fichier natif</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="466"/>
<source>Import native...</source>
- <translation type="unfinished"></translation>
+ <translation>Importer natif...</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="467"/>
<source>Import native file</source>
- <translation type="unfinished"></translation>
+ <translation>Importer un fichier natif</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="479"/>
<source>Save</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="479"/>
<source>Save the document</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer le document</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="484"/>
<source>Save as...</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer sous...</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="484"/>
<source>Save the document into a file</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer le document dans un fichier</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="506"/>
<source>Open...</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrir...</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="506"/>
<source>Open a new document</source>
- <translation type="unfinished"></translation>
+ <translation>Ouvrir un nouveau document</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="511"/>
<source>Auto rebuild</source>
- <translation type="unfinished"></translation>
+ <translation>Reconstruction automatique</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="512"/>
<source>Blocks immediate apply of modifications</source>
- <translation type="unfinished"></translation>
+ <translation>Bloque l'application immédiate des modifications</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="517"/>
<source>Preferences</source>
- <translation type="unfinished"></translation>
+ <translation>Préférences</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="517"/>
<source>Edit preferences</source>
- <translation type="unfinished"></translation>
+ <translation>Modifier les préférences</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="521"/>
<source>Exit</source>
- <translation type="unfinished"></translation>
+ <translation>Quitter</translation>
</message>
<message>
<location filename="XGUI_Workshop.cpp" line="521"/>
<source>Exit application</source>
- <translation type="unfinished"></translation>
+ <translation>Quitter l’application</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="930"/>
- <location filename="XGUI_Workshop.cpp" line="1029"/>
+ <location filename="XGUI_Workshop.cpp" line="931"/>
+ <location filename="XGUI_Workshop.cpp" line="1034"/>
<source>Save current file</source>
- <translation type="unfinished"></translation>
+ <translation>Enregistrer le fichier courant</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="931"/>
+ <location filename="XGUI_Workshop.cpp" line="932"/>
<source>The document is modified, save before opening another?</source>
- <translation type="unfinished"></translation>
+ <translation>Le document est modifié, sauvegarder avant d'en ouvrir un autre ?</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="942"/>
+ <location filename="XGUI_Workshop.cpp" line="946"/>
<source>Open file</source>
- <translation type="unfinished"></translation>
+ <translation>Fichier ouvert</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="1109"/>
+ <location filename="XGUI_Workshop.cpp" line="1117"/>
<source>Select name to save file...</source>
- <translation type="unfinished"></translation>
+ <translation>Sélectionnez le nom pour enregistrer le fichier...</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="1772"/>
+ <location filename="XGUI_Workshop.cpp" line="1782"/>
<source>Show object</source>
- <translation type="unfinished"></translation>
+ <translation>Montrer l'objet</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="1773"/>
+ <location filename="XGUI_Workshop.cpp" line="1783"/>
<source>'%1'
are hidden by %2:
Remove objects from the panel to be displayed?</source>
- <translation type="unfinished"></translation>
+ <translation>'%1'
+ est caché par %2 :
+Supprimer des objets du panneau à afficher ?</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="956"/>
+ <location filename="XGUI_Workshop.cpp" line="961"/>
<source>Warning</source>
- <translation type="unfinished"></translation>
+ <translation>Attention</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="956"/>
+ <location filename="XGUI_Workshop.cpp" line="961"/>
<source>Unable to open the file.</source>
- <translation type="unfinished"></translation>
+ <translation>Impossible d'ouvrir le fichier.</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="1029"/>
+ <location filename="XGUI_Workshop.cpp" line="1034"/>
<source>The document is modified, save before exit?</source>
- <translation type="unfinished"></translation>
+ <translation>Le document est modifié, enregistrer avant de quitter ?</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="1241"/>
+ <location filename="XGUI_Workshop.cpp" line="1251"/>
<source>Information about module "%1" doesn't exist.</source>
- <translation type="unfinished"></translation>
+ <translation>Les informations sur le module "%1" n'existent pas.</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="1402"/>
+ <location filename="XGUI_Workshop.cpp" line="1412"/>
<source>Object browser</source>
- <translation type="unfinished"></translation>
+ <translation>Navigateur d'objet</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="2005"/>
+ <location filename="XGUI_Workshop.cpp" line="2031"/>
<source>All features are relevant, there is nothing to be deleted</source>
- <translation type="unfinished"></translation>
+ <translation>Toutes les fonctionnalités sont pertinentes, il n'y a rien à supprimer</translation>
+ </message>
+ <message>
+ <location filename="XGUI_Workshop.cpp" line="2486"/>
+ <source>Transparency</source>
+ <translation>Transparence</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="2827"/>
+ <location filename="XGUI_Workshop.cpp" line="2866"/>
<source>Find results</source>
- <translation type="unfinished"></translation>
+ <translation>Trouver des résultats</translation>
</message>
<message>
- <location filename="XGUI_Workshop.cpp" line="2828"/>
+ <location filename="XGUI_Workshop.cpp" line="2867"/>
<source>Results not found</source>
- <translation type="unfinished"></translation>
+ <translation>Résultats non trouvés</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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+h_marche=18
+model.addParameter(Part_1_doc, "h_marche", str(h_marche))
+model.addParameter(Part_1_doc, "angle", "35")
+nb_marches=25
+h_totale=nb_marches*(h_marche+1)
+
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(13.86513942972648, 15.13114452817127, 113.484609238901, 23.84671880293715)
+SketchLine_2 = Sketch_1.addLine(124.230417176185, 14, 124.230417176185, 0)
+SketchLine_3 = Sketch_1.addLine(model.selection("EDGE", "PartSet/OX"))
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.result())
+SketchConstraintCoincidence_1.setName("SketchConstraintCoincidence_2")
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchArc_1 = Sketch_1.addArc(15.1889430421138, 0, 0, 0, 13.86513942972648, 15.13114452817127, True)
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_3.result(), SketchArc_1.center())
+SketchConstraintCoincidence_2.setName("SketchConstraintCoincidence_3")
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_3.startPoint(), SketchArc_1.startPoint())
+SketchConstraintCoincidence_3.setName("SketchConstraintCoincidence_4")
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchArc_1.endPoint())
+SketchConstraintCoincidence_4.setName("SketchConstraintCoincidence_5")
+SketchConstraintTangent_1 = Sketch_1.setTangent(SketchLine_1.result(), SketchArc_1.results()[1])
+SketchArc_2 = Sketch_1.addArc(114.3460855070856, 14, 124.230417176185, 14, 113.484609238901, 23.84671880293715, False)
+SketchConstraintCoincidence_5 = Sketch_1.setCoincident(SketchArc_2.startPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_5.setName("SketchConstraintCoincidence_6")
+SketchConstraintCoincidence_6 = Sketch_1.setCoincident(SketchArc_2.endPoint(), SketchLine_1.endPoint())
+SketchConstraintCoincidence_6.setName("SketchConstraintCoincidence_7")
+SketchConstraintTangent_2 = Sketch_1.setTangent(SketchArc_2.results()[1], SketchLine_2.result())
+SketchConstraintTangent_3 = Sketch_1.setTangent(SketchArc_2.results()[1], SketchLine_1.result())
+SketchConstraintMirror_1_objects = [SketchArc_1.results()[1], SketchLine_1.result(), SketchArc_2.results()[1], SketchLine_2.result()]
+SketchConstraintMirror_1 = Sketch_1.addMirror(SketchLine_3.result(), SketchConstraintMirror_1_objects)
+[SketchArc_3, SketchLine_4, SketchArc_4, SketchLine_5] = SketchConstraintMirror_1.mirrored()
+SketchConstraintAngle_1 = Sketch_1.setAngleBackward(SketchLine_1.result(), SketchLine_3.result(), 5)
+SketchConstraintLength_1 = Sketch_1.setLength(SketchLine_1.result(), 100)
+SketchConstraintLength_2 = Sketch_1.setLength(SketchLine_2.result(), 14)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchArc_1_2f-SketchArc_3_2f-SketchLine_4f-SketchArc_4_2f-SketchLine_5f-SketchLine_2r-SketchArc_2_2f-SketchLine_1r")], model.selection(), 5, 0)
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchProjection_1 = Sketch_2.addProjection(model.selection("VERTEX", "Sketch_1/SketchArc_1"), True)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchCircle_1 = Sketch_2.addCircle(15.1889430421138, 0, 9.469961851384218)
+SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchPoint_1.result(), SketchCircle_1.center())
+SketchConstraintCoincidence_7.setName("SketchConstraintCoincidence_8")
+model.do()
+# 1st step :
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2f")], model.selection(), h_totale, 0)
+Axis_4 = model.addAxis(Part_1_doc, model.selection("FACE", "Extrusion_2_1/Generated_Face&Sketch_2/SketchCircle_1_2"))
+model.do()
+# Cycle : use previous step to get the next one, translated and rotated
+stairFeature = Extrusion_1
+# 15 steps now to fille the whole cylinder, but it may be changed
+for step in range(nb_marches):
+ Translation = model.addTranslation(Part_1_doc, [stairFeature.result()], model.selection("EDGE", "PartSet/OZ"), "h_marche")
+ Recover = model.addRecover(Part_1_doc, Translation, [stairFeature.result()])
+ Rotation = model.addRotation(Part_1_doc, [Translation.result()], model.selection("EDGE", "Axis_1"), "angle")
+ model.do() # next transaction
+ stairFeature = Rotation # store the next step feature to translate/rotate it in the next iteration
+
+#====================================================================================
+model.end()
+
+assert(Part_1_doc.size("Bodies") == nb_marches + 2)
+model.testResultsVolumes(stairFeature, [23382.6888388])
+
+assert(model.checkPythonDump())