CMAKE_MINIMUM_REQUIRED(VERSION 2.8.10)
PROJECT (SHAPER)
-SET (SHAPER_Version 2.3.0)
+SET (SHAPER_Version 2.3.1)
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMakeCommon" ${CMAKE_MODULE_PATH})
#
# Modify plugins.xml to switch solver
-export PLUGINS_PATH=${PLUGINS_PATH:-${SHAPER_ROOT_DIR}/plugins/plugins.xml}
+export PLUGINS_PATH=${PLUGINS_PATH:-${SHAPER_ROOT_DIR}/share/salome/resources/shaper/plugins.xml}
while [[ $# > 0 ]]; do
key="$1"
// Get wires from faces.
ListOfShape aWires;
for(ListOfShape::const_iterator anIt = aFaces.cbegin(); anIt != aFaces.cend(); ++anIt) {
- for(GeomAPI_ShapeExplorer anExp(*anIt, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
- aWires.push_back(anExp.current());
- }
+ aWires.push_back(GeomAlgoAPI_ShapeTools::getFaceOuterWire(*anIt));
+ //for(GeomAPI_ShapeExplorer anExp(*anIt, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
+ // if(anExp.current()->orientation() == GeomAPI_Shape::REVERSED) {
+ // continue;
+ // }
+ // aWires.push_back(anExp.current());
+ //}
}
// Make faces with holes.
if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
return;
}
- ResultPtr aContext = aShapeAttrSelection->context();
aSubShapesAttrList->clear();
+ ResultPtr aContext = aShapeAttrSelection->context();
+
GeomShapePtr aBaseShape = aShapeAttrSelection->value();
if(!aBaseShape.get()) {
return;
// Copy sub-shapes from list to new shape.
if(!aShapesToAdd.empty()) {
- aBuilder.add(aResultShape, aShapesToAdd);
+ aBuilder.addInternal(aResultShape, aShapesToAdd);
aResultShape = aBuilder.shape();
}
std::shared_ptr<GeomAPI_Edge> anEdgeInList(new GeomAPI_Edge(aSelection->value()));
ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelection->context());
- std::shared_ptr<GeomAPI_PlanarEdges> aPlanarEdges = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aConstruction->shape());
- // Iterate on faces and add face with this edge.
- std::shared_ptr<GeomAPI_Face> aFoundFace;
+ // Iterate on wires and add wire with this edge.
+ std::shared_ptr<GeomAPI_Shape> aFoundWire;
for(int anIndex = 0; anIndex < aConstruction->facesNum(); ++anIndex) {
std::shared_ptr<GeomAPI_Face> aFace = aConstruction->face(anIndex);
- for(GeomAPI_ShapeExplorer anExp(aFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
- std::shared_ptr<GeomAPI_Edge> anEdgeOnFace(new GeomAPI_Edge(anExp.current()));
- if(anEdgeInList->isEqual(anEdgeOnFace)) {
- aFoundFace = aFace;
- break;
+ for(GeomAPI_ShapeExplorer aWireExp(aFace, GeomAPI_Shape::WIRE); aWireExp.more(); aWireExp.next()) {
+ GeomShapePtr aWireOnFace = aWireExp.current();
+ for(GeomAPI_ShapeExplorer anExp(aWireOnFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ std::shared_ptr<GeomAPI_Edge> anEdgeOnFace(new GeomAPI_Edge(anExp.current()));
+ if(anEdgeInList->isEqual(anEdgeOnFace)) {
+ aFoundWire = aWireOnFace;
+ break;
+ }
}
}
-
- if(aFoundFace.get()) {
+ if(aFoundWire.get()) {
break;
}
}
- // If face with the same edge found. Add all other edges to list.
- if(aFoundFace.get()) {
- for(GeomAPI_ShapeExplorer anExp(aFoundFace, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
+ // If wire with the same edge found. Add all other edges to list.
+ if(aFoundWire.get()) {
+ for(GeomAPI_ShapeExplorer anExp(aFoundWire, GeomAPI_Shape::EDGE); anExp.more(); anExp.next()) {
std::shared_ptr<GeomAPI_Edge> anEdgeOnFace(new GeomAPI_Edge(anExp.current()));
ListOfShape::const_iterator anEdgesIt = anAddedEdges.cbegin();
for(; anEdgesIt != anAddedEdges.cend(); ++anEdgesIt) {
label="Shape:"
tooltip="Select a shape to modify."
shape_types="objects"
- concealment="true">
+ concealment="true"
+ greed="true">
<validator id="GeomValidators_ShapeType" parameters="wire,face"/>
</shape_selector>
<multi_selector id="subshapes"
# Prepare plugins.xml
# the solver to activate after installation
-SET(DEFAULT_SOLVER "SolveSpace")
+SET(DEFAULT_SOLVER "PlaneGCS")
# the list of all solvers
SET(SOLVERS "SolveSpace" "PlaneGCS")
FeaturesPlugin_RevolutionFuse.h
FeaturesPlugin_ValidatorTransform.h
FeaturesPlugin_Validators.h
+ FeaturesPlugin_RemoveSubShapes.h
)
SET(PROJECT_SOURCES
FeaturesPlugin_RevolutionFuse.cpp
FeaturesPlugin_ValidatorTransform.cpp
FeaturesPlugin_Validators.cpp
+ FeaturesPlugin_RemoveSubShapes.cpp
)
SET(XML_RESOURCES
placement_widget.xml
intersection_widget.xml
pipe_widget.xml
+ remove_subshapes_widget.xml
)
INCLUDE_DIRECTORIES(
#include <map>
#include <sstream>
+static void storeSubShape(ResultBodyPtr theResultBody,
+ const GeomShapePtr theShape,
+ const GeomAPI_Shape::ShapeType theType,
+ const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+ const std::string theName,
+ int& theShapeIndex,
+ int& theTag);
+
//=================================================================================================
void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
{
GeomShapePtr aBaseShape = aBaseObjectSelection->value();
if(aBaseShape.get() && !aBaseShape->isNull()) {
GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
- if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE && aST != GeomAPI_Shape::WIRE &&
- aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
+ if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
setError("Error: Selected shapes has unsupported type.");
return;
}
}
// Searching faces with common edges.
- if(theIsMakeShells) {
+ if(theIsMakeShells && aBaseFacesList.size() > 1) {
ListOfShape aShells;
ListOfShape aFreeFaces;
GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
switch(aBaseShapeType) {
case GeomAPI_Shape::VERTEX: {
aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
- aGenName += "Edge";
break;
}
case GeomAPI_Shape::EDGE:
case GeomAPI_Shape::FACE:
case GeomAPI_Shape::SHELL: {
aShapeTypeToExplode = GeomAPI_Shape::EDGE;
- aGenName += "Face";
break;
}
+ case GeomAPI_Shape::COMPOUND: {
+ aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
+ }
+ }
+
+ if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+ theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::VERTEX,
+ theTag++, aGenName + "Edge", *aMapOfSubShapes.get());
+ }
+ if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+ theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, GeomAPI_Shape::EDGE,
+ theTag++, aGenName + "Face", *aMapOfSubShapes.get());
}
- theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, aShapeTypeToExplode,
- theTag++, aGenName, *aMapOfSubShapes.get());
std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep = std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
if(aMakeSweep.get()) {
aShapeTypeStr = "Face";
break;
}
+ case GeomAPI_Shape::COMPOUND: {
+ aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
+ break;
+ }
}
// Store shapes.
int aShapeIndex = 1;
- std::string aName = theName + aShapeTypeStr;
+ int aFaceIndex = 1;
for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
GeomShapePtr aShape = *anIt;
- for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
- GeomShapePtr aSubShape = anExp.current();
- if(theMapOfSubShapes->isBound(aSubShape)) {
- aSubShape = theMapOfSubShapes->find(aSubShape);
- }
- std::ostringstream aStr;
- aStr << aName << "_" << aShapeIndex++;
- theResultBody->generated(aSubShape, aStr.str(), theTag++);
+
+ if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
+ std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
+ storeSubShape(theResultBody,
+ aShape,
+ aShape->shapeType(),
+ theMapOfSubShapes,
+ aName,
+ aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
+ theTag);
+ } else {
+ std::string aName = theName + aShapeTypeStr;
+ storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
+ theMapOfSubShapes, aName, aShapeIndex, theTag);
+ }
+ }
+}
+
+void storeSubShape(ResultBodyPtr theResultBody,
+ const GeomShapePtr theShape,
+ const GeomAPI_Shape::ShapeType theType,
+ const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+ const std::string theName,
+ int& theShapeIndex,
+ int& theTag)
+{
+ for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
+ GeomShapePtr aSubShape = anExp.current();
+ if(theMapOfSubShapes->isBound(aSubShape)) {
+ aSubShape = theMapOfSubShapes->find(aSubShape);
}
+ std::ostringstream aStr;
+ aStr << theName << "_" << theShapeIndex++;
+ theResultBody->generated(aSubShape, aStr.str(), theTag++);
}
-}
\ No newline at end of file
+}
anObjects.push_back(anObject);
}
}
+
+ if(anObjects.empty()) {
+ static const std::string aFeatureError = "Error: No objects for partition.";
+ setError(aFeatureError);
+ return;
+ }
+
std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
// Resize planes.
// Store modified shape.
if(aBaseShape->isEqual(theResultShape)) {
aResultBody->store(theResultShape);
+ setResult(aResultBody, theIndex);
return;
}
#include <map>
#include <sstream>
-//=================================================================================================
+static void storeSubShape(ResultBodyPtr theResultBody,
+ const GeomShapePtr theShape,
+ const GeomAPI_Shape::ShapeType theType,
+ const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+ const std::string theName,
+ int& theShapeIndex,
+ int& theTag);
+
+//==================================================================================================
FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
{
}
-//=================================================================================================
+//==================================================================================================
void FeaturesPlugin_Pipe::initAttributes()
{
data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
}
-//=================================================================================================
+//==================================================================================================
void FeaturesPlugin_Pipe::execute()
{
// Getting creation method.
removeResults(aResultIndex);
}
-//=================================================================================================
+//==================================================================================================
void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
GeomAlgoAPI_Pipe& thePipeAlgo,
const int theResultIndex)
switch(aBaseShapeType) {
case GeomAPI_Shape::VERTEX: {
aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
- aGenName += "Edge";
break;
}
case GeomAPI_Shape::EDGE:
case GeomAPI_Shape::FACE:
case GeomAPI_Shape::SHELL: {
aShapeTypeToExplode = GeomAPI_Shape::EDGE;
- aGenName += "Face";
break;
}
+ case GeomAPI_Shape::COMPOUND: {
+ aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
+ }
+ }
+
+ if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+ aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
+ aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
+ }
+ if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
+ aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
+ aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
}
+
aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
// Store from shapes.
setResult(aResultBody, theResultIndex);
}
-//=================================================================================================
+//==================================================================================================
void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
GeomAlgoAPI_Pipe& thePipeAlgo,
const int theResultIndex)
setResult(aResultBody, theResultIndex);
}
-//=================================================================================================
+//==================================================================================================
void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
const GeomAPI_Shape::ShapeType theBaseShapeType,
const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
aShapeTypeStr = "Face";
break;
}
+ case GeomAPI_Shape::COMPOUND: {
+ aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
+ break;
+ }
}
// Store shapes.
int aShapeIndex = 1;
- std::string aName = theName + aShapeTypeStr;
+ int aFaceIndex = 1;
for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
- std::shared_ptr<GeomAPI_Shape> aShape = *anIt;
- for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
- std::shared_ptr<GeomAPI_Shape> aSubShape = anExp.current();
- if(theMapOfSubShapes->isBound(aSubShape)) {
- aSubShape = theMapOfSubShapes->find(aSubShape);
- }
- std::ostringstream aStr;
- aStr << aName << "_" << aShapeIndex++;
- theResultBody->generated(aSubShape, aStr.str(), theTag++);
+ GeomShapePtr aShape = *anIt;
+
+ if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
+ std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
+ storeSubShape(theResultBody,
+ aShape,
+ aShape->shapeType(),
+ theMapOfSubShapes,
+ aName,
+ aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
+ theTag);
+ } else {
+ std::string aName = theName + aShapeTypeStr;
+ storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
+ theMapOfSubShapes, aName, aShapeIndex, theTag);
+ }
+ }
+}
+
+//==================================================================================================
+void storeSubShape(ResultBodyPtr theResultBody,
+ const GeomShapePtr theShape,
+ const GeomAPI_Shape::ShapeType theType,
+ const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
+ const std::string theName,
+ int& theShapeIndex,
+ int& theTag)
+{
+ for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
+ GeomShapePtr aSubShape = anExp.current();
+ if(theMapOfSubShapes->isBound(aSubShape)) {
+ aSubShape = theMapOfSubShapes->find(aSubShape);
}
+ std::ostringstream aStr;
+ aStr << theName << "_" << theShapeIndex++;
+ theResultBody->generated(aSubShape, aStr.str(), theTag++);
}
}
#include <FeaturesPlugin_Partition.h>
#include <FeaturesPlugin_Pipe.h>
#include <FeaturesPlugin_Placement.h>
+#include <FeaturesPlugin_RemoveSubShapes.h>
#include <FeaturesPlugin_Revolution.h>
#include <FeaturesPlugin_RevolutionCut.h>
#include <FeaturesPlugin_RevolutionFuse.h>
new FeaturesPlugin_ValidatorBooleanSelection);
aFactory->registerValidator("FeaturesPlugin_ValidatorPartitionSelection",
new FeaturesPlugin_ValidatorPartitionSelection);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesSelection",
+ new FeaturesPlugin_ValidatorRemoveSubShapesSelection);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorRemoveSubShapesResult",
+ new FeaturesPlugin_ValidatorRemoveSubShapesResult);
+ aFactory->registerValidator("FeaturesPlugin_ValidatorPipePath",
+ new FeaturesPlugin_ValidatorPipePath);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
return FeaturePtr(new FeaturesPlugin_RevolutionCut);
} else if (theFeatureID == FeaturesPlugin_RevolutionFuse::ID()) {
return FeaturePtr(new FeaturesPlugin_RevolutionFuse);
+ } else if (theFeatureID == FeaturesPlugin_RemoveSubShapes::ID()) {
+ return FeaturePtr(new FeaturesPlugin_RemoveSubShapes);
}
// feature of such kind is not found
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: FeaturesPlugin_RemoveSubShapes.cpp
+// Created: 14 April 2016
+// Author: Dmitry Bobylev
+
+#include "FeaturesPlugin_RemoveSubShapes.h"
+
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_ResultBody.h>
+#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultConstruction.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
+
+#include <GeomAPI_ShapeIterator.h>
+
+#include <GeomAlgoAPI_ShapeBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
+//==================================================================================================
+FeaturesPlugin_RemoveSubShapes::FeaturesPlugin_RemoveSubShapes()
+{
+}
+
+//==================================================================================================
+void FeaturesPlugin_RemoveSubShapes::initAttributes()
+{
+ data()->addAttribute(BASE_SHAPE_ID(), ModelAPI_AttributeSelection::typeId());
+
+ data()->addAttribute(SUBSHAPES_ID(), ModelAPI_AttributeSelectionList::typeId());
+}
+
+void FeaturesPlugin_RemoveSubShapes::attributeChanged(const std::string& theID)
+{
+ ModelAPI_Feature::attributeChanged(theID);
+
+ if(theID == BASE_SHAPE_ID()) {
+ AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+ AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID());
+ if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
+ return;
+ }
+
+ aSubShapesAttrList->clear();
+
+ ResultPtr aContext = aShapeAttrSelection->context();
+ ResultCompSolidPtr aResultCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
+ if(!aResultCompSolid.get()) {
+ return;
+ }
+
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ if(!aBaseShape.get()) {
+ aBaseShape = aContext->shape();
+ }
+ if(!aBaseShape.get()) {
+ return;
+ }
+ GeomAPI_Shape::ShapeType aShapeType = aBaseShape->shapeType();
+ if(aShapeType != GeomAPI_Shape::WIRE
+ && aShapeType != GeomAPI_Shape::SHELL
+ && aShapeType != GeomAPI_Shape::COMPSOLID
+ && aShapeType != GeomAPI_Shape::COMPOUND) {
+ return;
+ }
+ for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
+ GeomShapePtr aSubShape = anIt.current();
+ const int aNumOfSubs = aResultCompSolid->numberOfSubs();
+ if(aNumOfSubs == 0) {
+ aSubShapesAttrList->append(aContext, aSubShape);
+ } else {
+ for(int anIndex = 0; anIndex < aResultCompSolid->numberOfSubs(); ++anIndex) {
+ ResultBodyPtr aSubResult = aResultCompSolid->subResult(anIndex);
+ if(aSubResult->shape()->isEqual(aSubShape)) {
+ aSubShapesAttrList->append(aSubResult, aSubShape);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+//==================================================================================================
+void FeaturesPlugin_RemoveSubShapes::execute()
+{
+ // Get base shape and sub-shapes list.
+ AttributeSelectionPtr aShapeAttrSelection = selection(BASE_SHAPE_ID());
+ AttributeSelectionListPtr aSubShapesAttrList = selectionList(SUBSHAPES_ID());
+ if(!aShapeAttrSelection.get() || !aSubShapesAttrList.get()) {
+ return;
+ }
+
+ // Copy base shape.
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ if(!aBaseShape.get()) {
+ return;
+ }
+ GeomShapePtr aResultShape = aBaseShape->emptyCopied();
+
+ // Copy sub-shapes from list to new shape.
+ for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+ GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+ GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
+ }
+
+ // Store result.
+ ResultBodyPtr aResultBody = document()->createBody(data());
+ aResultBody->storeModified(aBaseShape, aResultShape);
+ setResult(aResultBody);
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: FeaturesPlugin_RemoveSubShapes.h
+// Created: 23 May 2016
+// Author: Dmitry Bobylev
+
+#ifndef FeaturesPlugin_RemoveSubShapes_H_
+#define FeaturesPlugin_RemoveSubShapes_H_
+
+#include "FeaturesPlugin.h"
+
+#include <ModelAPI_Feature.h>
+
+/// \class FeaturesPlugin_RemoveSubShapes
+/// \ingroup Plugins
+/// \brief Feature for removing sub-shapes from collections(wire, shell, compsolid, compound).
+class FeaturesPlugin_RemoveSubShapes: public ModelAPI_Feature
+{
+public:
+ /// Use plugin manager for features creation
+ FeaturesPlugin_RemoveSubShapes();
+
+ /// Feature kind.
+ inline static const std::string& ID()
+ {
+ static const std::string MY_ID("Remove_SubShapes");
+ return MY_ID;
+ }
+
+ /// Attribute name of base shape.
+ inline static const std::string& BASE_SHAPE_ID()
+ {
+ static const std::string MY_BASE_SHAPE_ID("base_shape");
+ return MY_BASE_SHAPE_ID;
+ }
+
+ /// Attribute name of sub-shapes.
+ inline static const std::string& SUBSHAPES_ID()
+ {
+ static const std::string MY_SUBSHAPES_ID("subshapes");
+ return MY_SUBSHAPES_ID;
+ }
+
+ /// \return the kind of a feature.
+ FEATURESPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = FeaturesPlugin_RemoveSubShapes::ID();
+ return MY_KIND;
+ }
+
+ /// Request for initialization of data model of the feature: adding all attributes.
+ FEATURESPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object.
+ /// \param[in] theID identifier of changed attribute.
+ FEATURESPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Creates a new part document if needed.
+ FEATURESPLUGIN_EXPORT virtual void execute();
+};
+
+#endif
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_AttributeReference.h>
#include <ModelAPI_Feature.h>
+#include <ModelAPI_ResultCompSolid.h>
#include <ModelAPI_ResultConstruction.h>
#include <GeomValidators_BodyShapes.h>
#include <GeomAPI_DataMapOfShapeShape.h>
#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAPI_ShapeIterator.h>
+
+#include <GeomAlgoAPI_ShapeBuilder.h>
+#include <GeomAlgoAPI_ShapeTools.h>
#include <GeomAlgoAPI_WireBuilder.h>
+//==================================================================================================
+bool FeaturesPlugin_ValidatorPipePath::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const
+{
+ AttributeSelectionPtr aPathAttrSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+ if(!aPathAttrSelection.get()) {
+ theError = "Error: This validator can only work with path selector in \"Pipe\" feature.";
+ return false;
+ }
+
+ GeomShapePtr aPathShape = aPathAttrSelection->value();
+ ResultPtr aContext = aPathAttrSelection->context();
+ if(!aContext.get()) {
+ theError = "Error: Empty context.";
+ return false;
+ }
+ GeomShapePtr aContextShape = aContext->shape();
+ if(aPathShape.get() && aPathShape->shapeType() == GeomAPI_Shape::WIRE && !aPathShape->isEqual(aContextShape)) {
+ theError = "Error: Local selection of wires not allowed.";
+ return false;
+ }
+
+ return true;
+}
+
//==================================================================================================
bool FeaturesPlugin_ValidatorPipeLocations::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const std::list<std::string>& theArguments,
static const std::string aLocationsID = "locations_objects";
if(theFeature->getKind() != "Pipe") {
- theError = "Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
+ theError = "Error: Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
return false;
}
AttributeStringPtr aCreationMethodAttr = theFeature->string(aCreationMethodID);
if(!aCreationMethodAttr.get()) {
- theError = "Could not get \"" + aCreationMethodID + "\" attribute.";
+ theError = "Error: Could not get \"" + aCreationMethodID + "\" attribute.";
return false;
}
AttributeSelectionListPtr aBaseObjectsSelectionList = theFeature->selectionList(aBaseObjectsID);
if(!aBaseObjectsSelectionList.get()) {
- theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
+ theError = "Error: Could not get \"" + aBaseObjectsID + "\" attribute.";
return false;
}
AttributeSelectionListPtr aLocationsSelectionList = theFeature->selectionList(aLocationsID);
if(!aLocationsSelectionList.get()) {
- theError = "Could not get \"" + aBaseObjectsID + "\" attribute.";
+ theError = "Error: Could not get \"" + aBaseObjectsID + "\" attribute.";
return false;
}
if(aLocationsSelectionList->size() > 0 && aLocationsSelectionList->size() != aBaseObjectsSelectionList->size()) {
- theError = "Number of locations should be the same as base objects.";
+ theError = "Error: Number of locations should be the same as base objects.";
return false;
}
std::string& theError) const
{
if(theArguments.empty()) {
- theError = "Validator parameters is empty.";
+ theError = "Error: Validator parameters is empty.";
return false;
}
// Checking attribute.
if(!isValidAttribute(theAttribute, theArguments, theError)) {
if(theError.empty()) {
- theError = "Attribute contains unacceptable shape.";
+ theError = "Error: Attribute contains unacceptable shape.";
}
return false;
}
AttributeSelectionListPtr aListAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
for(int anIndex = 0; anIndex < aListAttr->size(); ++anIndex) {
AttributeSelectionPtr aSelectionAttr = aListAttr->value(anIndex);
- ResultConstructionPtr aContext = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSelectionAttr->context());
+ ResultPtr aContext = aSelectionAttr->context();
if(!aContext.get()) {
- // It is not a result construction, continue.
+ theError = "Error: Empty context.";
+ return false;
+ }
+
+ ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+ if(!aResultConstruction.get()) {
+ // It is not a result construction. If shape is compound check that it contains only faces and edges.
+ GeomShapePtr aShape = aSelectionAttr->value();
+ if(!aShape.get()) {
+ aShape = aContext->shape();
+ }
+
+ if(aShape->shapeType() == GeomAPI_Shape::COMPOUND) {
+ for(GeomAPI_ShapeIterator anIt(aShape); anIt.more(); anIt.next()) {
+ GeomShapePtr aSubShape = anIt.current();
+ if(aSubShape->shapeType() != GeomAPI_Shape::EDGE
+ && aSubShape->shapeType() != GeomAPI_Shape::FACE) {
+ theError = "Error: Compound should contain only faces and edges.";
+ return false;
+ }
+ }
+ }
+
continue;
}
GeomShapePtr aShape = aSelectionAttr->value();
- GeomShapePtr aContextShape = aContext->shape();
+ GeomShapePtr aContextShape = aResultConstruction->shape();
if(!aShape.get()) {
// Whole sketch selected.
- if(aSelectedSketchesFromObjects.find(aContext) != aSelectedSketchesFromObjects.cend()) {
- theError = "Object from this sketch is already selected. Sketch is not allowed for selection.";
+ if(aSelectedSketchesFromObjects.find(aResultConstruction) != aSelectedSketchesFromObjects.cend()) {
+ theError = "Error: Object from this sketch is already selected. Sketch is not allowed for selection.";
return false;
}
- aSelectedSketches.insert(aContext);
+ aSelectedSketches.insert(aResultConstruction);
} else {
// Object from sketch selected.
- if(aSelectedSketches.find(aContext) != aSelectedSketches.cend()) {
- theError = "Whole sketch with this object is already selected. Don't allow to select this object.";
+ if(aSelectedSketches.find(aResultConstruction) != aSelectedSketches.cend()) {
+ theError = "Error: Whole sketch with this object is already selected. Don't allow to select this object.";
return false;
}
for(GeomAPI_ShapeExplorer anExp(aShape, GeomAPI_Shape::WIRE); anExp.more(); anExp.next()) {
GeomShapePtr aWire = anExp.current();
if(aWire->orientation() != GeomAPI_Shape::FORWARD) {
- theError = "Wire with wrong orientation selected.";
+ theError = "Error: Wire with wrong orientation selected.";
return false;
}
if(aSelectedWiresFromObjects.isBound(aWire)) {
- theError = "Objects with such wire already selected. Don't allow to select this object.";
+ theError = "Error: Objects with such wire already selected. Don't allow to select this object.";
return false;
}
aSelectedWiresFromObjects.bind(aWire, aWire);
- aSelectedSketchesFromObjects.insert(aContext);
+ aSelectedSketchesFromObjects.insert(aResultConstruction);
}
}
}
std::string& theError) const
{
if(!theAttribute.get()) {
- theError = "Empty attribute.";
+ theError = "Error: Empty attribute.";
return false;
}
AttributeSelectionPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
ResultPtr aContext = anAttr->context();
if(!aContext.get()) {
- theError = "Attribute have empty context.";
+ theError = "Error: Attribute have empty context.";
return false;
}
aShape = aContextShape;
}
if(!aShape.get()) {
- theError = "Empty shape selected";
+ theError = "Error: Empty shape selected";
return false;
}
if(aConstruction.get()) {
// Construciotn selected. Check that is is not infinite.
if(aConstruction->isInfinite()) {
- theError = "Infinite constructions is not allowed as base.";
+ theError = "Error: Infinite constructions is not allowed as base.";
return false;
}
if(!aShape->isEqual(aContextShape)) {
// Local selection on body does not allowed.
- theError = "Selected shape is in the local selection. Only global selection is allowed.";
+ theError = "Error: Selected shape is in the local selection. Only global selection is allowed.";
return false;
}
// Check that object is a shape with allowed type.
GeomValidators_ShapeType aShapeTypeValidator;
if(!aShapeTypeValidator.isValid(anAttr, theArguments, theError)) {
- theError = "Selected shape has unacceptable type. Acceptable types are: faces or wires on sketch, "
+ theError = "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: ";
std::list<std::string>::const_iterator anIt = theArguments.cbegin();
theError += *anIt;
}
} else {
- theError = "Following attribute does not supported: " + anAttributeType + ".";
+ theError = "Error: Attribute \"" + anAttributeType + "\" does not supported by this validator.";
return false;
}
std::string& theError) const
{
if (theAttribute->attributeType() != ModelAPI_AttributeReference::typeId()) {
- theError = "The attribute with the " + theAttribute->attributeType() + " type is not processed";
+ theError = "Error: The attribute with the " + theAttribute->attributeType() + " type is not processed";
return false;
}
if (theArguments.size() != 2) {
- theError = "Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
+ theError = "Error: Wrong parameters in XML definition for " + theAttribute->attributeType() + " type";
return false;
}
// first argument is for the base attribute, second - for skipping feature kind
std::string& theError) const
{
if(theArguments.size() != 2) {
- theError = "Validator should be used with 2 parameters for extrusion.";
+ theError = "Error: Validator should be used with 2 parameters for extrusion.";
return false;
}
AttributeSelectionPtr aSelAttr = theFeature->selection(*anArgsIt);
if(!aSelAttr.get()) {
- theError = "Could not get selection attribute \"" + *anArgsIt + "\".";
+ theError = "Error: Could not get selection attribute \"" + *anArgsIt + "\".";
return false;
}
if(!aShape.get()) {
ResultPtr aContext = aSelAttr->context();
if(!aContext.get()) {
- theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
+ theError = "Error: Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
+ "\" can not be used with default value. Select direction for extrusion.";
return false;
}
}
if(!aShape.get()) {
- theError = "Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
+ theError = "Error: Base objects list contains vertex or edge, so attribute \"" + *anArgsIt
+ "\" can not be used with default value. Select direction for extrusion.";
return false;
}
{
AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
if(!anAttrSelectionList.get()) {
- theError = "Error: this validator can only work with selection list attributes in Boolean feature.";
+ theError = "Error: This validator can only work with selection list attributes in \"Boolean\" feature.";
return false;
}
FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
if(!anAttrSelection.get()) {
- theError = "Error: empty attribute selection.";
+ theError = "Error: Empty attribute selection.";
return false;
}
ResultPtr aContext = anAttrSelection->context();
if(!aContext.get()) {
- theError = "Error: empty selection context.";
+ theError = "Error: Empty selection context.";
return false;
}
ResultConstructionPtr aResultConstruction =
aShape = aContext->shape();
}
if(!aShape.get()) {
- theError = "Error: empty shape.";
+ theError = "Error: Empty shape.";
return false;
}
int aShapeType = aShape->shapeType();
aShapeType != GeomAPI_Shape::SOLID &&
aShapeType != GeomAPI_Shape::COMPSOLID &&
aShapeType != GeomAPI_Shape::COMPOUND) {
- theError = "Error: selected shape has the wrong type.";
+ theError = "Error: Selected shape has the wrong type.";
return false;
}
} else {
if(aShapeType != GeomAPI_Shape::SOLID &&
aShapeType != GeomAPI_Shape::COMPSOLID &&
aShapeType != GeomAPI_Shape::COMPOUND) {
- theError = "Error: selected shape has the wrong type.";
+ theError = "Error: Selected shape has the wrong type.";
return false;
}
}
const std::list<std::string>& theArguments,
std::string& theError) const
{
- std::string anAttributeType = theAttribute->attributeType();
- if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
- AttributeSelectionListPtr aSelectionListAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ AttributeSelectionListPtr anAttrSelectionList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if(!anAttrSelectionList.get()) {
+ theError = "Error: This validator can only work with selection list in \"Partition\" feature.";
+ return false;
+ }
- for(int anIndex = 0; anIndex < aSelectionListAttr->size(); ++anIndex) {
- AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex);
+ for(int anIndex = 0; anIndex < anAttrSelectionList->size(); ++anIndex) {
+ AttributeSelectionPtr aSelectAttr = anAttrSelectionList->value(anIndex);
- GeomValidators_BodyShapes aBodyValidator;
- if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
- continue;
- }
+ //GeomValidators_BodyShapes aBodyValidator;
+ //if(aBodyValidator.isValid(aSelectAttr, theArguments, theError)) {
+ // continue;
+ //}
- GeomValidators_FeatureKind aFeatureKindValidator;
- if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
- continue;
- }
+ GeomValidators_FeatureKind aFeatureKindValidator;
+ if(aFeatureKindValidator.isValid(aSelectAttr, theArguments, theError)) {
+ continue;
+ }
- theError = "Only body shapes and construction planes are allowed for selection.";
+ ResultPtr aContext = aSelectAttr->context();
+ ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+ if(aResultConstruction.get()) {
+ theError = "Error: Only body shapes and construction planes are allowed for selection.";
return false;
}
- } else {
- theError = "This validator supports only " + ModelAPI_AttributeSelectionList::typeId() + " attribute type.";
+
+ ResultCompSolidPtr aResultCompsolid = std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(aContext);
+ if(aResultCompsolid.get()) {
+ continue;
+ }
+
+ theError = "Error: Only body shapes and construction planes are allowed for selection.";
+ return false;
+ }
+
+ theError = "";
+ return true;
+}
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorRemoveSubShapesSelection::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const
+{
+ AttributeSelectionListPtr aSubShapesAttrList = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
+ if(!aSubShapesAttrList.get()) {
+ theError = "Error: This validator can only work with selection list in \"Remove Sub-Shapes\" feature.";
+ return false;
+ }
+
+ static const std::string aBaseShapeID = "base_shape";
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributeSelectionPtr aShapeAttrSelection = aFeature->selection(aBaseShapeID);
+
+ if(!aShapeAttrSelection.get()) {
+ theError = "Error: Could not get \"" + aBaseShapeID + "\" attribute.";
+ return false;
+ }
+
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ ResultPtr aContext = aShapeAttrSelection->context();
+ if(!aContext.get()) {
+ theError = "Error: Empty context.";
+ return false;
+ }
+ if(!aBaseShape.get()) {
+ aBaseShape = aContext->shape();
+ }
+ if(!aBaseShape.get()) {
+ theError = "Error: Empty base shape.";
return false;
}
+ for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+ bool isSameFound = false;
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+ GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+ for(GeomAPI_ShapeIterator anIt(aBaseShape); anIt.more(); anIt.next()) {
+ if(anIt.current()->isEqual(aShapeToAdd)) {
+ isSameFound = true;
+ break;
+ }
+ }
+ if(!isSameFound) {
+ theError = "Error: Only sub-shapes of selected shape is allowed for selection.";
+ return false;
+ }
+ }
+
return true;
}
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const
+{
+ static const std::string aBaseShapeID = "base_shape";
+ static const std::string aSubShapesID = "subshapes";
+
+ if(theFeature->getKind() != "Remove_SubShapes") {
+ theError = "Error: Feature \"" + theFeature->getKind() + "\" does not supported by this validator.";
+ return false;
+ }
+
+ AttributeSelectionPtr aShapeAttrSelection = theFeature->selection(aBaseShapeID);
+ if(!aShapeAttrSelection.get()) {
+ theError = "Error: Could not get \"" + aBaseShapeID + "\" attribute.";
+ return false;
+ }
+
+ AttributeSelectionListPtr aSubShapesAttrList = theFeature->selectionList(aSubShapesID);
+ if(!aSubShapesAttrList.get()) {
+ theError = "Error: Could not get \"" + aSubShapesID + "\" attribute.";
+ return false;
+ }
+
+ // Copy base shape.
+ GeomShapePtr aBaseShape = aShapeAttrSelection->value();
+ if(!aBaseShape.get()) {
+ return false;
+ }
+ GeomShapePtr aResultShape = aBaseShape->emptyCopied();
+
+ // Copy sub-shapes from list to new shape.
+ for(int anIndex = 0; anIndex < aSubShapesAttrList->size(); ++anIndex) {
+ AttributeSelectionPtr anAttrSelectionInList = aSubShapesAttrList->value(anIndex);
+ GeomShapePtr aShapeToAdd = anAttrSelectionInList->value();
+ GeomAlgoAPI_ShapeBuilder::add(aResultShape, aShapeToAdd);
+ }
+
+ // Check new shape.
+ if(!GeomAlgoAPI_ShapeTools::isShapeValid(aResultShape)) {
+ theError = "Error: Resulting shape is not valid.";
+ return false;
+ }
+
+ return true;
+}
+
+//==================================================================================================
+bool FeaturesPlugin_ValidatorRemoveSubShapesResult::isNotObligatory(std::string theFeature,
+ std::string theAttribute)
+{
+ return false;
+}
#include <ModelAPI_AttributeValidator.h>
#include <ModelAPI_FeatureValidator.h>
+/// \class FeaturesPlugin_ValidatorPipePath
+/// \ingroup Validators
+/// \brief A validator for selection pipe path.
+class FeaturesPlugin_ValidatorPipePath: public ModelAPI_AttributeValidator
+{
+public:
+ //! \return True if the attribute is valid.
+ //! \param[in] theAttribute the checked attribute.
+ //! \param[in] theArguments arguments of the attribute.
+ //! \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const;
+};
+
/// \class FeaturesPlugin_ValidatorPipeLocations
/// \ingroup Validators
/// \brief Validator for the pipe locations.
class FeaturesPlugin_ValidatorBaseForGeneration: public ModelAPI_AttributeValidator
{
public:
- //! Returns true if attribute has selection type listed in the parameter arguments.
+ //! \return true if attribute has selection type listed in the parameter arguments.
//! \param[in] theAttribute the checked attribute.
//! \param[in] theArguments arguments of the attribute.
//! \param[out] theError error message.
class FeaturesPlugin_ValidatorCompositeLauncher: public ModelAPI_AttributeValidator
{
public:
- //! Returns true if attribute has selection type listed in the parameter arguments.
+ //! \return true if attribute has selection type listed in the parameter arguments.
//! \param[in] theAttribute the checked attribute.
//! \param[in] theArguments arguments of the attribute.
//! \param[out] theError error message.
class FeaturesPlugin_ValidatorCanBeEmpty: public ModelAPI_FeatureValidator
{
public:
- //! Returns true if attribute listed in the parameter arguments are planar.
+ //! \return true if attribute listed in the parameter arguments are planar.
//! \param[in] theFeature the checked feature.
//! \param[in] theArguments arguments of the attribute.
//! \param[out] theError error message.
const std::list<std::string>& theArguments,
std::string& theError) const;
- /// Returns true if the attribute in feature is not obligatory for the feature execution
+ /// \return true if the attribute in feature is not obligatory for the feature execution
virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
private:
{
public:
/// \return True if the attribute is valid. It checks whether the selection
- /// is acceptable for boolean operation.
+ /// is acceptable for operation.
+ /// \param[in] theAttribute an attribute to check.
+ /// \param[in] theArguments a filter parameters.
+ /// \param[out] theError error message.
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const;
+};
+
+/// \class FeaturesPlugin_ValidatorRemoveSubShapesSelection
+/// \ingroup Validators
+/// \brief Validates selection for "Remove Sub-Shapes" feature.
+class FeaturesPlugin_ValidatorRemoveSubShapesSelection: public ModelAPI_AttributeValidator
+{
+public:
+ /// \return True if the attribute is valid. It checks whether the selection
+ /// is acceptable for operation.
/// \param[in] theAttribute an attribute to check.
/// \param[in] theArguments a filter parameters.
/// \param[out] theError error message.
std::string& theError) const;
};
+/// \class FeaturesPlugin_ValidatorRemoveSubShapesResult
+/// \ingroup Validators
+/// \brief Validator for the Remove Sub-Shapes feature.
+class FeaturesPlugin_ValidatorRemoveSubShapesResult: public ModelAPI_FeatureValidator
+{
+ public:
+ //! \return true if result is valid shape.
+ //! \param theFeature the checked feature
+ //! \param theArguments arguments of the feature (not used)
+ //! \param theError error message
+ virtual bool isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const;
+
+ /// \return true if the attribute in feature is not obligatory for the feature execution
+ virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
+};
+
#endif
buttons_dir="horizontal"
label="Operation type"
tooltip="Type of boolean operation"
- string_list="Cut Fuse Common Fill Smash"
+ string_list="Cut Fuse Common Smash"
use_in_title="true"
- icons_list="icons/Features/bool_cut.png icons/Features/bool_fuse.png icons/Features/bool_common.png icons/Features/bool_fill.png icons/Features/bool_smash.png"
+ icons_list="icons/Features/bool_cut.png icons/Features/bool_fuse.png icons/Features/bool_common.png icons/Features/bool_smash.png"
default="0"
/>
<multi_selector id="main_objects"
tooltip="Select a base objects"
type_choice="wires faces objects"
concealment="true">
- <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+ <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
</multi_selector>
<shape_selector id="direction_object"
icon="icons/Features/axis.png"
icon="icons/Features/sketch.png"
tooltip="Select a sketch face"
type_choice="wires faces objects">
- <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+ <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
</multi_selector>
<shape_selector id="direction_object"
icon="icons/Features/axis.png"
concealment="true">
<validator id="FeaturesPlugin_ValidatorPartitionSelection" parameters="Plane"/>
</multi_selector>
+ <validator id="GeomValidators_MinObjectsSelected" parameters="base_objects,2"/>
</source>
type_choice="wires faces objects"
use_choice="false"
concealment="true">
- <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+ <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
</multi_selector>
<shape_selector id="path_object"
label="Path object:"
tooltip="Select an edge or wire for path"
shape_types="edge wire">
+ <validator id="FeaturesPlugin_ValidatorPipePath"/>
</shape_selector>
<toolbox id="creation_method">
<box id="simple" title="Simple pipe by objects and path" icon="icons/Features/pipe_simple_32x32.png"/>
auto_preview="false">
<source path="partition_widget.xml"/>
</feature>
+ <feature id="Remove_SubShapes" title="Remove Sub-Shapes" tooltip="Allows to remove sub-shapes from wires, shells, compsolids and compounds" icon="icons/Features/remove_subshapes.png">
+ <source path="remove_subshapes_widget.xml"/>
+ </feature>
<feature id="Intersection" title="Intersection" tooltip="Intersect objects with tools" icon="icons/Features/intersection.png">
<source path="intersection_widget.xml"/>
</feature>
--- /dev/null
+<!-- Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+<source>
+ <shape_selector id="base_shape"
+ label="Shape:"
+ tooltip="Select a shape to modify."
+ shape_types="objects"
+ concealment="true"
+ greed="true">
+ <validator id="GeomValidators_ShapeType" parameters="wire,shell,compsolid,compound"/>
+ <validator id="GeomValidators_BodyShapes"/>
+ </shape_selector>
+ <multi_selector id="subshapes"
+ label="Sub-Shapes:"
+ tooltip="Select shapes to keep."
+ type_choice="vertices edges wires faces shells solids compsolids compounds"
+ clear_in_neutral_point="false">
+ <validator id="FeaturesPlugin_ValidatorRemoveSubShapesSelection"/>
+ </multi_selector>
+ <validator id="FeaturesPlugin_ValidatorRemoveSubShapesResult"/>
+</source>
tooltip="Select a base objects"
type_choice="wires faces objects"
concealment="true">
- <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+ <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
</multi_selector>
<shape_selector id="axis_object"
icon="icons/Features/axis.png"
icon="icons/Features/sketch.png"
tooltip="Select a sketch face"
type_choice="wires faces objects">
- <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell"/>
+ <validator id="FeaturesPlugin_ValidatorBaseForGeneration" parameters="vertex,edge,wire,face,shell,compound"/>
</multi_selector>
<shape_selector id="axis_object"
icon="icons/Features/axis.png"
NCollection_List<TopoDS_Shape> aNew; // very new connected to new connected
NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotConnected);
while(aNotIter.More()) {
+ // optimization to avoid TopExp_Explorer double-cycle, collect all vertices in the list first
+ NCollection_List<TopoDS_Shape> aNotVertices;
+ for(TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX); anExp1.More(); anExp1.Next()) {
+ aNotVertices.Append(anExp1.Current());
+ }
+
bool aConnected = false;
NCollection_List<TopoDS_Shape>::Iterator aNewIter(aNewConnected);
for(; !aConnected && aNewIter.More(); aNewIter.Next()) {
// checking topological connecion of aNotIter and aNewIter (if shapes are connected, vertices are connected for sure)
- TopExp_Explorer anExp1(aNotIter.Value(), TopAbs_VERTEX);
- for(; !aConnected && anExp1.More(); anExp1.Next()) {
- TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
- for(; anExp2.More(); anExp2.Next()) {
- if (anExp1.Current().IsSame(anExp2.Current())) {
+ TopExp_Explorer anExp2(aNewIter.Value(), TopAbs_VERTEX);
+ for(; !aConnected && anExp2.More(); anExp2.Next()) {
+ NCollection_List<TopoDS_Shape>::Iterator aNotIter(aNotVertices);
+ for(; aNotIter.More(); aNotIter.Next()) {
+ if (aNotIter.Value().IsSame(anExp2.Current())) {
aConnected = true;
break;
}
{
public:
/// \returns the list of from shapes.
- GEOMALGOAPI_EXPORT virtual const ListOfShape& fromShapes() const;
+ GEOMALGOAPI_EXPORT const ListOfShape& fromShapes() const;
/// \return the list of to shapes.
- GEOMALGOAPI_EXPORT virtual const ListOfShape& toShapes() const;
-
-protected:
- /// Empty constructor.
- GeomAlgoAPI_MakeSweep() : GeomAlgoAPI_MakeShapeList() {};
+ GEOMALGOAPI_EXPORT const ListOfShape& toShapes() const;
/// \brief Adds a shape to list of from shape.
/// \param[in] theShape a shape to add.
- void addFromShape(const std::shared_ptr<GeomAPI_Shape> theShape);
+ GEOMALGOAPI_EXPORT void addFromShape(const std::shared_ptr<GeomAPI_Shape> theShape);
/// \brief Sets from shapes
/// \param[in] theListOfShapes list of from shapes.
- void setFromShapes(const ListOfShape& theListOfShapes);
+ GEOMALGOAPI_EXPORT void setFromShapes(const ListOfShape& theListOfShapes);
/// \brief Adds a face to list of to shape.
/// \param[in] theShape a face to add.
- void addToShape(const std::shared_ptr<GeomAPI_Shape> theShape);
+ GEOMALGOAPI_EXPORT void addToShape(const std::shared_ptr<GeomAPI_Shape> theShape);
/// \brief Sets to shapes
/// \param[in] theListOfShapes list of to shapes.
- void setToShapes(const ListOfShape& theListOfShapes);
+ GEOMALGOAPI_EXPORT void setToShapes(const ListOfShape& theListOfShapes);
+
+protected:
+ /// Empty constructor.
+ GeomAlgoAPI_MakeSweep() : GeomAlgoAPI_MakeShapeList() {};
private:
ListOfShape myFromShapes;
static bool getPath(TopoDS_Wire& thePathOut,
const GeomShapePtr thePathShape);
static bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder);
+static ListOfShape getListFromShape(const TopoDS_Shape& theShape);
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
const GeomShapePtr thePathShape)
{
build(theBaseShape, thePathShape);
}
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const GeomShapePtr theBaseShape,
const GeomShapePtr thePathShape,
const GeomShapePtr theBiNormal)
build(theBaseShape, thePathShape, theBiNormal);
}
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Pipe::GeomAlgoAPI_Pipe(const ListOfShape& theBaseShapes,
const ListOfShape& theLocations,
const GeomShapePtr thePathShape)
build(theBaseShapes, theLocations, thePathShape);
}
-//=================================================================================================
+//==================================================================================================
void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
const GeomShapePtr thePathShape)
{
TopAbs_ShapeEnum aBaseShapeType = aBaseShape.ShapeType();
if(aBaseShapeType != TopAbs_VERTEX && aBaseShapeType != TopAbs_EDGE &&
aBaseShapeType != TopAbs_WIRE && aBaseShapeType != TopAbs_FACE &&
- aBaseShapeType != TopAbs_SHELL) {
+ aBaseShapeType != TopAbs_SHELL && aBaseShapeType != TopAbs_COMPOUND) {
return;
}
this->initialize(aPipeBuilder);
// Setting naming.
- GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
- aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape()));
- aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape()));
- this->addFromShape(aFromShape);
- this->addToShape(aToShape);
+ this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
+ this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
// Setting result.
TopoDS_Shape aResult = aPipeBuilder->Shape();
this->setDone(true);
}
-//=================================================================================================
+//==================================================================================================
void GeomAlgoAPI_Pipe::build(const GeomShapePtr theBaseShape,
const GeomShapePtr thePathShape,
const GeomShapePtr theBiNormal)
}
}
TopoDS_Shape aResult = aPipeBuilder->Shape();
+ if(aResult.IsNull()) {
+ return;
+ }
// Setting naming.
- GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
- aFromShape->setImpl(new TopoDS_Shape(aPipeBuilder->FirstShape()));
- aToShape->setImpl(new TopoDS_Shape(aPipeBuilder->LastShape()));
- this->addFromShape(aFromShape);
- this->addToShape(aToShape);
+ this->setToShapes(getListFromShape(aPipeBuilder->LastShape()));
+ this->setFromShapes(getListFromShape(aPipeBuilder->FirstShape()));
// Setting result.
- if(aResult.IsNull()) {
- return;
- }
aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
GeomShapePtr aGeomSh(new GeomAPI_Shape());
aGeomSh->setImpl(new TopoDS_Shape(aResult));
this->setDone(true);
}
-//=================================================================================================
+//==================================================================================================
void GeomAlgoAPI_Pipe::build(const ListOfShape& theBaseShapes,
const ListOfShape& theLocations,
const GeomShapePtr thePathShape)
this->setDone(true);
}
-//=================================================================================================
+//==================================================================================================
void GeomAlgoAPI_Pipe::generated(const GeomShapePtr theShape,
ListOfShape& theHistory)
{
}
// Auxilary functions:
-//=================================================================================================
+//==================================================================================================
bool getBase(TopoDS_Shape& theBaseOut,
TopAbs_ShapeEnum& theBaseTypeOut,
const GeomShapePtr theBaseShape)
return true;
}
-//=================================================================================================
+//==================================================================================================
bool getPath(TopoDS_Wire& thePathOut,
const GeomShapePtr thePathShape)
{
return true;
}
-//=================================================================================================
+//==================================================================================================
bool buildPipe(BRepOffsetAPI_MakePipeShell* thePipeBuilder)
{
thePipeBuilder->Build();
return isDone == Standard_True;
}
+
+//==================================================================================================
+ListOfShape getListFromShape(const TopoDS_Shape& theShape)
+{
+ ListOfShape aList;
+
+ TopAbs_ShapeEnum aType = theShape.ShapeType();
+ if(aType == TopAbs_WIRE || aType == TopAbs_SHELL || aType == TopAbs_COMPOUND) {
+ for(TopoDS_Iterator anIt(theShape); anIt.More(); anIt.Next()) {
+ GeomShapePtr aGeomShape(new GeomAPI_Shape());
+ aGeomShape->setImpl(new TopoDS_Shape(anIt.Value()));
+ aList.push_back(aGeomShape);
+ }
+ } else {
+ GeomShapePtr aGeomShape(new GeomAPI_Shape());
+ aGeomShape->setImpl(new TopoDS_Shape(theShape));
+ aList.push_back(aGeomShape);
+ }
+
+ return aList;
+}
#include <TopoDS_Solid.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
-//=================================================================================================
+
+static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakePrism* thePrismBuilder);
+
+static void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Face& theToFace,
+ const TopoDS_Face& theFromFace);
+
+
+//==================================================================================================
GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
const double theToSize,
const double theFromSize)
build(theBaseShape, std::shared_ptr<GeomAPI_Dir>(), GeomShapePtr(), theToSize, GeomShapePtr(), theFromSize);
}
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
const std::shared_ptr<GeomAPI_Dir> theDirection,
const double theToSize,
build(theBaseShape, theDirection, GeomShapePtr(), theToSize, GeomShapePtr(), theFromSize);
}
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
const GeomShapePtr theToShape,
const double theToSize,
build(theBaseShape, std::shared_ptr<GeomAPI_Dir>(), theToShape, theToSize, theFromShape, theFromSize);
}
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Prism::GeomAlgoAPI_Prism(const GeomShapePtr theBaseShape,
const std::shared_ptr<GeomAPI_Dir> theDirection,
const GeomShapePtr theToShape,
build(theBaseShape, theDirection, theToShape, theToSize, theFromShape, theFromSize);
}
-//=================================================================================================
+//==================================================================================================
void GeomAlgoAPI_Prism::build(const GeomShapePtr& theBaseShape,
const std::shared_ptr<GeomAPI_Dir> theDirection,
const GeomShapePtr& theToShape,
case TopAbs_SHELL:
aShapeTypeToExp = TopAbs_FACE;
break;
+ case TopAbs_COMPOUND:
+ aShapeTypeToExp = TopAbs_COMPOUND;
+ break;
default:
return;
}
aResult = aPrismBuilder->Shape();
// Setting naming.
- for(TopExp_Explorer anExp(aMovedBase, aShapeTypeToExp); anExp.More(); anExp.Next()) {
- const TopoDS_Shape& aShape = anExp.Current();
- GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
- aFromShape->setImpl(new TopoDS_Shape(aPrismBuilder->FirstShape(aShape)));
- aToShape->setImpl(new TopoDS_Shape(aPrismBuilder->LastShape(aShape)));
- this->addFromShape(aFromShape);
- this->addToShape(aToShape);
+ if(aShapeTypeToExp == TopAbs_COMPOUND) {
+ storeGenerationHistory(this, aMovedBase, TopAbs_EDGE, aPrismBuilder);
+ storeGenerationHistory(this, aMovedBase, TopAbs_FACE, aPrismBuilder);
+ } else {
+ storeGenerationHistory(this, aMovedBase, aShapeTypeToExp, aPrismBuilder);
}
} else {
GeomShapePtr aBoundingFromShape = theFromShape ? theFromShape : aBasePlane;
if(aResult.ShapeType() == TopAbs_COMPOUND) {
aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
}
- if(aShapeTypeToExp == TopAbs_FACE) {
+ if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
const TopTools_ListOfShape& aToShapes = aToCutBuilder->Modified(aToShape);
for(TopTools_ListIteratorOfListOfShape anIt(aToShapes); anIt.More(); anIt.Next()) {
GeomShapePtr aGeomSh(new GeomAPI_Shape());
if(aResult.ShapeType() == TopAbs_COMPOUND) {
aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
}
- if(aShapeTypeToExp == TopAbs_FACE) {
+ if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
const TopTools_ListOfShape& aFromShapes = aFromCutBuilder->Modified(aFromShape);
for(TopTools_ListIteratorOfListOfShape anIt(aFromShapes); anIt.More(); anIt.Next()) {
GeomShapePtr aGeomSh(new GeomAPI_Shape());
}
// Naming for extrusion from vertex, edge.
- for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More(); anExp.Next()) {
- const TopoDS_Shape& aShape = anExp.Current();
- GeomShapePtr aGeomSh(new GeomAPI_Shape());
- if(aShapeTypeToExp == TopAbs_VERTEX) {
- gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
- IntTools_Context anIntTools;
- if(anIntTools.IsValidPointForFace(aPnt, aToFace, Precision::Confusion()) == Standard_True) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addToShape(aGeomSh);
- }
- if(anIntTools.IsValidPointForFace(aPnt, aFromFace, Precision::Confusion()) == Standard_True) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addFromShape(aGeomSh);
- }
- } else if(aShapeTypeToExp == TopAbs_EDGE) {
- TopoDS_Edge anEdge = TopoDS::Edge(aShape);
- BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, aToFace);
- anEdgeCheck.Perform();
- if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addToShape(aGeomSh);
- }
- anEdgeCheck.Init(anEdge, aFromFace);
- anEdgeCheck.Perform();
- if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addFromShape(aGeomSh);
- }
- } else {
- break;
- }
+ if(aShapeTypeToExp == TopAbs_COMPOUND) {
+ storeGenerationHistory(this, aResult, TopAbs_EDGE, aToFace, aFromFace);
+ storeGenerationHistory(this, aResult, TopAbs_FACE, aToFace, aFromFace);
+ } else {
+ storeGenerationHistory(this, aResult, aShapeTypeToExp, aToFace, aFromFace);
}
if(aResult.ShapeType() == TopAbs_COMPOUND) {
this->setShape(aGeomSh);
this->setDone(true);
}
+
+// Auxilary functions:
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakePrism* thePrismBuilder)
+{
+ for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
+ aFromShape->setImpl(new TopoDS_Shape(thePrismBuilder->FirstShape(aShape)));
+ aToShape->setImpl(new TopoDS_Shape(thePrismBuilder->LastShape(aShape)));
+ thePrismAlgo->addFromShape(aFromShape);
+ thePrismAlgo->addToShape(aToShape);
+ }
+}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Prism* thePrismAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Face& theToFace,
+ const TopoDS_Face& theFromFace)
+{
+ for(TopExp_Explorer anExp(theResult, theType); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ if(theType == TopAbs_VERTEX) {
+ gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+ IntTools_Context anIntTools;
+ if(anIntTools.IsValidPointForFace(aPnt, theToFace, Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->addToShape(aGeomSh);
+ }
+ if(anIntTools.IsValidPointForFace(aPnt, theFromFace, Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->addFromShape(aGeomSh);
+ }
+ } else if(theType == TopAbs_EDGE) {
+ TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+ BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, theToFace);
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->addToShape(aGeomSh);
+ }
+ anEdgeCheck.Init(anEdge, theFromFace);
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ thePrismAlgo->addFromShape(aGeomSh);
+ }
+ } else {
+ break;
+ }
+ }
+}
/// \return solid.
static TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint);
-//=================================================================================================
+static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakeRevol* theRevolBuilder);
+
+static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Shape& theToFace,
+ const TopoDS_Shape& theFromFace);
+
+static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Shape& theRotatedBoundingFace,
+ const TopoDS_Shape& theModifiedBaseShape,
+ const bool theIsFromFaceSet);
+
+//==================================================================================================
GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr theBaseShape,
const std::shared_ptr<GeomAPI_Ax1> theAxis,
const double theToAngle,
build(theBaseShape, theAxis, GeomShapePtr(), theToAngle, GeomShapePtr(), theFromAngle);
}
-//=================================================================================================
+//==================================================================================================
GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr theBaseShape,
const std::shared_ptr<GeomAPI_Ax1> theAxis,
const GeomShapePtr theToShape,
build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
}
-//=================================================================================================
+//==================================================================================================
void GeomAlgoAPI_Revolution::build(const GeomShapePtr& theBaseShape,
const std::shared_ptr<GeomAPI_Ax1>& theAxis,
const GeomShapePtr& theToShape,
case TopAbs_SHELL:
aShapeTypeToExp = TopAbs_FACE;
break;
+ case TopAbs_COMPOUND:
+ aShapeTypeToExp = TopAbs_COMPOUND;
+ break;
default:
return;
}
aResult = aRevolBuilder->Shape();
// Setting naming.
- for(TopExp_Explorer anExp(aRotatedBase, aShapeTypeToExp); anExp.More(); anExp.Next()) {
- const TopoDS_Shape& aShape = anExp.Current();
- GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
- aFromShape->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape(aShape)));
- aToShape->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape(aShape)));
- this->addFromShape(aFromShape);
- this->addToShape(aToShape);
+ if(aShapeTypeToExp == TopAbs_COMPOUND) {
+ storeGenerationHistory(this, aRotatedBase, TopAbs_EDGE, aRevolBuilder);
+ storeGenerationHistory(this, aRotatedBase, TopAbs_FACE, aRevolBuilder);
+ } else {
+ storeGenerationHistory(this, aRotatedBase, aShapeTypeToExp, aRevolBuilder);
}
} else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
// Making revolution to the 360 angle.
aResult = findClosest(aResult, aBaseCentre);
// Setting naming.
- for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
- const TopoDS_Shape& aShape = anExp.Current();
- GeomShapePtr aGeomSh(new GeomAPI_Shape());
- if(aShapeTypeToExp == TopAbs_VERTEX) {
- gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
- IntTools_Context anIntTools;
- if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedToFace), Precision::Confusion()) == Standard_True) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addToShape(aGeomSh);
- }
- if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedFromFace), Precision::Confusion()) == Standard_True) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addFromShape(aGeomSh);
- }
- } else if(aShapeTypeToExp == TopAbs_EDGE) {
- TopoDS_Edge anEdge = TopoDS::Edge(aShape);
- BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedToFace));
- anEdgeCheck.Perform();
- if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addToShape(aGeomSh);
- }
- anEdgeCheck.Init(anEdge, TopoDS::Face(aRotatedFromFace));
- anEdgeCheck.Perform();
- if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addFromShape(aGeomSh);
- }
- } else {
- Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
- Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace));
- Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace));
- if(aFaceSurface == aFromSurface) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addFromShape(aGeomSh);
- }
- if(aFaceSurface == aToSurface) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- this->addToShape(aGeomSh);
- }
- }
+ if(aShapeTypeToExp == TopAbs_COMPOUND) {
+ storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedToFace, aRotatedFromFace);
+ storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedToFace, aRotatedFromFace);
+ } else {
+ storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedToFace, aRotatedFromFace);
}
} else { //Case 3: When only one bounding plane was set.
// Making revolution to the 360 angle.
}
// Setting naming.
- if(aShapeTypeToExp == TopAbs_FACE) {
+ if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
GeomShapePtr aShape(new GeomAPI_Shape());
if(aResult.ShapeType() == TopAbs_COMPOUND) {
aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
}
- if(aShapeTypeToExp == TopAbs_FACE) {
+ if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
GeomShapePtr aShape(new GeomAPI_Shape());
aResult = findClosest(aResult, aBaseCentre);
// Setting naming.
- for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
- const TopoDS_Shape& aShape = anExp.Current();
- GeomShapePtr aGeomSh(new GeomAPI_Shape());
- if(aShapeTypeToExp == TopAbs_VERTEX) {
- gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
- IntTools_Context anIntTools;
- if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
- }
- if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aModifiedBaseShape), Precision::Confusion()) == Standard_True) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
- }
- } else if(aShapeTypeToExp == TopAbs_EDGE) {
- TopoDS_Edge anEdge = TopoDS::Edge(aShape);
- BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedBoundingFace));
- anEdgeCheck.Perform();
- if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
- }
- anEdgeCheck.Init(anEdge, TopoDS::Face(aModifiedBaseShape));
- anEdgeCheck.Perform();
- if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
- }
- } else {
- Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
- Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace));
- Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(aModifiedBaseShape));
- if(aFaceSurface == aBoundingSurface) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
- }
- if(aFaceSurface == aBaseSurface) {
- aGeomSh->setImpl(new TopoDS_Shape(aShape));
- isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
- }
- }
+ if(aShapeTypeToExp == TopAbs_COMPOUND) {
+ storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
+ storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
+ } else {
+ storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
}
}
this->setDone(true);
}
-//=================================================================================================
+//==================================================================================================
TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
{
if(!thePlane.Contains(thePoint, Precision::Confusion())) {
return aResultFace;
}
-//=================================================================================================
+//==================================================================================================
TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
{
TopoDS_Shell aShell;
return aSolid;
}
-//=================================================================================================
+//==================================================================================================
gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
{
TopAbs_ShapeEnum aShType = theShape.ShapeType();
return aGProps.CentreOfMass();
}
-//=================================================================================================
+//==================================================================================================
TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
{
TopoDS_Shape aResult = theShape;
return aResult;
}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+ const TopoDS_Shape& theBase,
+ const TopAbs_ShapeEnum theType,
+ BRepPrimAPI_MakeRevol* theRevolBuilder)
+{
+ for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
+ aFromShape->setImpl(new TopoDS_Shape(theRevolBuilder->FirstShape(aShape)));
+ aToShape->setImpl(new TopoDS_Shape(theRevolBuilder->LastShape(aShape)));
+ theRevolutionAlgo->addFromShape(aFromShape);
+ theRevolutionAlgo->addToShape(aToShape);
+ }
+}
+
+//==================================================================================================
+void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Shape& theToFace,
+ const TopoDS_Shape& theFromFace)
+{
+ for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ if(theType == TopAbs_VERTEX) {
+ gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+ IntTools_Context anIntTools;
+ if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theToFace), Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theRevolutionAlgo->addToShape(aGeomSh);
+ }
+ if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theFromFace), Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theRevolutionAlgo->addFromShape(aGeomSh);
+ }
+ } else if(theType == TopAbs_EDGE) {
+ TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+ BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theToFace));
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theRevolutionAlgo->addToShape(aGeomSh);
+ }
+ anEdgeCheck.Init(anEdge, TopoDS::Face(theFromFace));
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theRevolutionAlgo->addFromShape(aGeomSh);
+ }
+ } else {
+ Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
+ Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(theFromFace));
+ Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(theToFace));
+ if(aFaceSurface == aFromSurface) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theRevolutionAlgo->addFromShape(aGeomSh);
+ }
+ if(aFaceSurface == aToSurface) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theRevolutionAlgo->addToShape(aGeomSh);
+ }
+ }
+ }
+}
+
+void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
+ const TopoDS_Shape& theResult,
+ const TopAbs_ShapeEnum theType,
+ const TopoDS_Shape& theRotatedBoundingFace,
+ const TopoDS_Shape& theModifiedBaseShape,
+ const bool theIsFromFaceSet)
+{
+ for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
+ const TopoDS_Shape& aShape = anExp.Current();
+ GeomShapePtr aGeomSh(new GeomAPI_Shape());
+ if(theType == TopAbs_VERTEX) {
+ gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
+ IntTools_Context anIntTools;
+ if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
+ }
+ if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theModifiedBaseShape), Precision::Confusion()) == Standard_True) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
+ }
+ } else if(theType == TopAbs_EDGE) {
+ TopoDS_Edge anEdge = TopoDS::Edge(aShape);
+ BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theRotatedBoundingFace));
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
+ }
+ anEdgeCheck.Init(anEdge, TopoDS::Face(theModifiedBaseShape));
+ anEdgeCheck.Perform();
+ if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
+ }
+ } else {
+ Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
+ Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(theRotatedBoundingFace));
+ Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(theModifiedBaseShape));
+ if(aFaceSurface == aBoundingSurface) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
+ }
+ if(aFaceSurface == aBaseSurface) {
+ aGeomSh->setImpl(new TopoDS_Shape(aShape));
+ theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
+ }
+ }
+ }
+}
}
//==================================================================================================
-void GeomAlgoAPI_ShapeBuilder::add(const std::shared_ptr<GeomAPI_Shape> theShape,
- const ListOfShape& theShapesToAdd)
+void GeomAlgoAPI_ShapeBuilder::addInternal(const std::shared_ptr<GeomAPI_Shape> theShape,
+ const ListOfShape& theShapesToAdd)
{
// Get base shape.
if(!theShape.get()) {
/// \param[in] theShape base shape.
GEOMALGOAPI_EXPORT void removeInternal(const std::shared_ptr<GeomAPI_Shape> theShape);
- /// \brief Store new shape as result of adding theShapesToAdd to theShape.
+ /// \brief Store new shape as result of adding theShapesToAdd to theShape as internal shapes.
/// \param[in] theShape base shape.
/// \param[in] theShapesToAdd shapes which will be added.
- GEOMALGOAPI_EXPORT void add(const std::shared_ptr<GeomAPI_Shape> theShape,
- const ListOfShape& theShapesToAdd);
+ GEOMALGOAPI_EXPORT void addInternal(const std::shared_ptr<GeomAPI_Shape> theShape,
+ const ListOfShape& theShapesToAdd);
};
#endif
#include <BRepBuilderAPI_FindPlane.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRepCheck_Analyzer.hxx>
#include <BRepExtrema_DistShapeShape.hxx>
#include <BRepGProp.hxx>
+#include <BRepTools.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <Geom_Curve.hxx>
#include <Geom2d_Curve.hxx>
aBuilder.MakeCompound(aCompound);
ListOfShape aCompSolids, aFreeSolids;
for(NCollection_Vector<NCollection_List<TopoDS_Shape>>::Iterator anIt(aGroups); anIt.More(); anIt.Next()) {
- TopoDS_Compound aGroupCompound = makeCompound(anIt.Value());
+ NCollection_List<TopoDS_Shape> aGroup = anIt.Value();
GeomShapePtr aGeomShape(new GeomAPI_Shape());
- aGeomShape->setImpl(new TopoDS_Shape(aGroupCompound));
- aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
- GeomAPI_Shape::COMPSOLID,
- aCompSolids,
- aFreeSolids);
+ if(aGroup.Size() == 1) {
+ aGeomShape->setImpl(new TopoDS_Shape(aGroup.First()));
+ } else {
+ aGeomShape->setImpl(new TopoDS_Shape(makeCompound(anIt.Value())));
+ aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
+ GeomAPI_Shape::COMPSOLID,
+ aCompSolids,
+ aFreeSolids);
+ }
aBuilder.Add(aCompound, aGeomShape->impl<TopoDS_Shape>());
}
return true;
}
+
+//==================================================================================================
+bool GeomAlgoAPI_ShapeTools::isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape)
+{
+ if(!theShape.get()) {
+ return false;
+ }
+
+ BRepCheck_Analyzer aChecker(theShape->impl<TopoDS_Shape>());
+ return (aChecker.IsValid() == Standard_True);
+}
+
+//==================================================================================================
+std::shared_ptr<GeomAPI_Shape> GeomAlgoAPI_ShapeTools::getFaceOuterWire(const std::shared_ptr<GeomAPI_Shape> theFace)
+{
+ GeomShapePtr anOuterWire;
+
+ if(!theFace.get() || !theFace->isFace()) {
+ return anOuterWire;
+ }
+
+ TopoDS_Face aFace = TopoDS::Face(theFace->impl<TopoDS_Shape>());
+ TopoDS_Wire aWire = BRepTools::OuterWire(aFace);
+
+ anOuterWire.reset(new GeomAPI_Shape());
+ anOuterWire->setImpl(new TopoDS_Shape(aWire));
+
+ return anOuterWire;
+}
/// \return true if edge inside the face.
GEOMALGOAPI_EXPORT static bool isSubShapeInsideShape(const std::shared_ptr<GeomAPI_Shape> theSubShape,
const std::shared_ptr<GeomAPI_Shape> theBaseShape);
+
+ /// \return true if theShape is valid.
+ GEOMALGOAPI_EXPORT static bool isShapeValid(const std::shared_ptr<GeomAPI_Shape> theShape);
+
+ /// \return outer wire for face. If theShape has different type returns empty pointer.
+ GEOMALGOAPI_EXPORT static std::shared_ptr<GeomAPI_Shape> getFaceOuterWire(const std::shared_ptr<GeomAPI_Shape> theFace);
+
};
#endif
GeomValidators_ZeroOffset.h
GeomValidators_Different.h
GeomValidators_IntersectionSelection.h
+ GeomValidators_MinObjectsSelected.h
)
SET(PROJECT_SOURCES
GeomValidators_ZeroOffset.cpp
GeomValidators_Different.cpp
GeomValidators_IntersectionSelection.cpp
+ GeomValidators_MinObjectsSelected.cpp
)
SET(PROJECT_LIBRARIES
std::string& theError) const
{
std::string anAttributeType = theAttribute->attributeType();
- if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
- AttributeSelectionListPtr aSelectionListAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
- // all context objects should not be sketch entities
- for(int anIndex = 0, aSize = aSelectionListAttr->size(); anIndex < aSize; ++anIndex) {
- AttributeSelectionPtr aSelectAttr = aSelectionListAttr->value(anIndex);
- ResultPtr aContext = aSelectAttr->context();
- if(!aContext.get()) {
- theError = "Error: Context is empty.";
- return false;
- }
+ if(anAttributeType == ModelAPI_AttributeSelection::typeId()) {
+ AttributeSelectionPtr anAttrSelection =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+ ResultPtr aContext = anAttrSelection->context();
+ if(!aContext.get()) {
+ theError = "Error: Context is empty.";
+ return false;
+ }
+
+ ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+ if(aResultConstruction.get()) {
+ theError = "Error: Result construction selected.";
+ return false;
+ }
+ } else if(anAttributeType == ModelAPI_AttributeSelectionList::typeId()) {
+ AttributeSelectionListPtr anAttrSelectionList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(theAttribute);
- ResultConstructionPtr aResultConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
- if(aResultConstruction.get()) {
- theError = "Error: Result construction selected.";
+ // All objects should not be result constructions.
+ for(int anIndex = 0, aSize = anAttrSelectionList->size(); anIndex < aSize; ++anIndex) {
+ AttributeSelectionPtr anAttrSelection = anAttrSelectionList->value(anIndex);
+ if(!isValid(anAttrSelection, theArguments, theError)) {
return false;
}
}
+ } else {
+ theError = "Error: Attribute \"" + anAttributeType + "\" does not supported by this validator.";
+ return false;
}
return true;
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomValidators_MinObjectsSelected.cpp
+// Created: 30 June 2015
+// Author: Dmitry Bobylev
+
+#include <GeomValidators_MinObjectsSelected.h>
+
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeSelectionList.h>
+
+//=================================================================================================
+bool GeomValidators_MinObjectsSelected::isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const
+{
+ if(theArguments.size() != 2) {
+ theError = "Error: Wrong number of arguments (expected 2): selection list id and min number of objects";
+ return false;
+ }
+
+ std::string aSelectionListId = theArguments.front();
+ AttributeSelectionListPtr anAttrSelList = theFeature->selectionList(aSelectionListId);
+ if(!anAttrSelList.get()) {
+ theError = "Error: Could not get attribute \"" + aSelectionListId + "\".";
+ return false;
+ }
+ int anObjectsNb = anAttrSelList->size();
+
+ int aMinObjectsNb = atoi(theArguments.back().c_str());
+
+ if(anObjectsNb < aMinObjectsNb) {
+ theError = "Error: Attribute \"" + aSelectionListId + "\" should contain at least "
+ + theArguments.back() + " items.";
+ return false;
+ }
+
+ return true;
+}
+
+//=================================================================================================
+bool GeomValidators_MinObjectsSelected::isNotObligatory(std::string theFeature, std::string theAttribute)
+{
+ return false;
+}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: GeomValidators_MinObjectsSelected.h
+// Created: 30 June 2015
+// Author: Dmitry Bobylev
+
+#ifndef GeomValidators_MinObjectsSelected_H
+#define GeomValidators_MinObjectsSelected_H
+
+#include <GeomValidators.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_FeatureValidator.h>
+
+/// \class GeomValidators_MinObjectsSelected
+/// \ingroup Validators
+/// \brief Validates number of objects in selection list.
+class GeomValidators_MinObjectsSelected : public ModelAPI_FeatureValidator
+{
+public:
+ /// \return true if selection list has enough objects.
+ /// \param[in] theFeature the validated feature.
+ /// \param[in] theArguments the arguments in the configuration file for this validator.
+ /// \param[out] theError error message.
+ /// \returns true if feature is valid.
+ GEOMVALIDATORS_EXPORT virtual bool isValid(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::list<std::string>& theArguments,
+ std::string& theError) const;
+
+ /// \return true if the attribute in feature is not obligatory for the feature execution.
+ GEOMVALIDATORS_EXPORT virtual bool isNotObligatory(std::string theFeature, std::string theAttribute);
+};
+
+#endif
#include <GeomValidators_ZeroOffset.h>
#include <GeomValidators_IntersectionSelection.h>
#include <GeomValidators_FeatureKind.h>
+#include <GeomValidators_MinObjectsSelected.h>
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
aFactory->registerValidator("GeomValidators_ZeroOffset", new GeomValidators_ZeroOffset);
aFactory->registerValidator("GeomValidators_IntersectionSelection", new GeomValidators_IntersectionSelection);
aFactory->registerValidator("GeomValidators_FeatureKind", new GeomValidators_FeatureKind);
+ aFactory->registerValidator("GeomValidators_MinObjectsSelected", new GeomValidators_MinObjectsSelected);
// register this plugin
ModelAPI_Session::get()->registerPlugin(this);
GeomValidators_ShapeType::TypeOfShape GeomValidators_ShapeType::shapeType(const std::string& theType)
{
if (MyShapeTypes.size() == 0) {
- MyShapeTypes["empty"] = Empty;
- MyShapeTypes["vertex"] = Vertex;
- MyShapeTypes["edge"] = Edge;
- MyShapeTypes["line"] = Line;
- MyShapeTypes["circle"] = Circle;
- MyShapeTypes["wire"] = Wire;
- MyShapeTypes["face"] = Face;
- MyShapeTypes["plane"] = Plane;
- MyShapeTypes["shell"] = Shell;
- MyShapeTypes["solid"] = Solid;
+ MyShapeTypes["empty"] = Empty;
+ MyShapeTypes["vertex"] = Vertex;
+ MyShapeTypes["edge"] = Edge;
+ MyShapeTypes["line"] = Line;
+ MyShapeTypes["circle"] = Circle;
+ MyShapeTypes["wire"] = Wire;
+ MyShapeTypes["face"] = Face;
+ MyShapeTypes["plane"] = Plane;
+ MyShapeTypes["shell"] = Shell;
+ MyShapeTypes["solid"] = Solid;
+ MyShapeTypes["compsolid"] = CompSolid;
+ MyShapeTypes["compound"] = Compound;
}
std::string aType = std::string(theType.c_str());
if (MyShapeTypes.find(aType) != MyShapeTypes.end())
aValid = theShape->isSolid() || theShape->isCompSolid() ||
theShape->isCompoundOfSolids();
break;
+ case CompSolid:
+ aValid = theShape->shapeType() == GeomAPI_Shape::COMPSOLID;
+ break;
case Compound:
aValid = theShape->isCompound();
break;
Plane,
Shell,
Solid,
+ CompSolid,
Compound,
AnyShape
};
TDataStd_ListIteratorOfListOfExtendedString anIDIter(anIDList);
for (; aLIter.More(); aLIter.Next(), anIDIter.Next()) {
ObjectPtr anObj;
- if (!aLIter.Value().IsNull())
+ if (!aLIter.Value().IsNull()) {
anObj = aDoc->objects()->object(aLIter.Value());
- aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj,
- anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
+ aResult.push_back(std::pair<ObjectPtr, AttributePtr>(anObj,
+ anObj->data()->attribute(TCollection_AsciiString(anIDIter.Value()).ToCString())));
+ } else {
+ aResult.push_back(std::pair<ObjectPtr, AttributePtr>(ObjectPtr(), AttributePtr()));
+ }
}
}
return aResult;
#include <TNaming_SameShapeIterator.hxx>
#include <TNaming_Iterator.hxx>
#include <TNaming_NamedShape.hxx>
+#include <TNaming_Tool.hxx>
#include <TopExp_Explorer.hxx>
#include <climits>
while(!theShape.IsNull()) { // searching for the very initial shape that produces this one
TopoDS_Shape aShape = theShape;
theShape.Nullify();
+ if (!TNaming_Tool::HasLabel(aMain, aShape)) // to avoid crash of TNaming_SameShapeIterator if pure shape does not exists
+ break;
for(TNaming_SameShapeIterator anIter(aShape, aMain); anIter.More(); anIter.Next()) {
TDF_Label aNSLab = anIter.Label();
Handle(TNaming_NamedShape) aNS;
{
myBuilder = new Model_BodyBuilder(this);
myWasConcealed = false;
+ myConnect = ConnectionNotComputed;
}
void Model_ResultBody::initAttributes()
/// Flag that stores the previous state of "concealed": if it is changed,
/// The event is used to redisplay the body.
bool myWasConcealed;
+
public:
/// Request for initialization of data model of the result: adding all attributes
virtual void initAttributes();
TopAbs_ShapeEnum translateType (const std::string& theType)
{
// map from the textual shape types to OCCT enumeration
- static std::map<std::string, TopAbs_ShapeEnum> MyShapeTypes;
- if (MyShapeTypes.size() == 0) {
- MyShapeTypes["face"] = TopAbs_FACE;
- MyShapeTypes["faces"] = TopAbs_FACE;
- MyShapeTypes["vertex"] = TopAbs_VERTEX;
- MyShapeTypes["vertices"] = TopAbs_VERTEX;
- MyShapeTypes["wire"] = TopAbs_WIRE;
- MyShapeTypes["edge"] = TopAbs_EDGE;
- MyShapeTypes["edges"] = TopAbs_EDGE;
- MyShapeTypes["shell"] = TopAbs_SHELL;
- MyShapeTypes["solid"] = TopAbs_SOLID;
- MyShapeTypes["solids"] = TopAbs_SOLID;
- MyShapeTypes["FACE"] = TopAbs_FACE;
- MyShapeTypes["FACES"] = TopAbs_FACE;
- MyShapeTypes["VERTEX"] = TopAbs_VERTEX;
- MyShapeTypes["VERTICES"] = TopAbs_VERTEX;
- MyShapeTypes["WIRE"] = TopAbs_WIRE;
- MyShapeTypes["EDGE"] = TopAbs_EDGE;
- MyShapeTypes["EDGES"] = TopAbs_EDGE;
- MyShapeTypes["SHELL"] = TopAbs_SHELL;
- MyShapeTypes["SOLID"] = TopAbs_SOLID;
- MyShapeTypes["SOLIDS"] = TopAbs_SOLID;
+ static std::map<std::string, TopAbs_ShapeEnum> aShapeTypes;
+
+ if(aShapeTypes.size() == 0) {
+ aShapeTypes["compound"] = TopAbs_COMPOUND;
+ aShapeTypes["compounds"] = TopAbs_COMPOUND;
+ aShapeTypes["compsolid"] = TopAbs_COMPSOLID;
+ aShapeTypes["compsolids"] = TopAbs_COMPSOLID;
+ aShapeTypes["solid"] = TopAbs_SOLID;
+ aShapeTypes["solids"] = TopAbs_SOLID;
+ aShapeTypes["shell"] = TopAbs_SHELL;
+ aShapeTypes["shells"] = TopAbs_SHELL;
+ aShapeTypes["face"] = TopAbs_FACE;
+ aShapeTypes["faces"] = TopAbs_FACE;
+ aShapeTypes["wire"] = TopAbs_WIRE;
+ aShapeTypes["wires"] = TopAbs_WIRE;
+ aShapeTypes["edge"] = TopAbs_EDGE;
+ aShapeTypes["edges"] = TopAbs_EDGE;
+ aShapeTypes["vertex"] = TopAbs_VERTEX;
+ aShapeTypes["vertices"] = TopAbs_VERTEX;
+ aShapeTypes["COMPOUND"] = TopAbs_COMPOUND;
+ aShapeTypes["COMPOUNDS"] = TopAbs_COMPOUND;
+ aShapeTypes["COMPSOLID"] = TopAbs_COMPSOLID;
+ aShapeTypes["COMPSOLIDS"] = TopAbs_COMPSOLID;
+ aShapeTypes["SOLID"] = TopAbs_SOLID;
+ aShapeTypes["SOLIDS"] = TopAbs_SOLID;
+ aShapeTypes["SHELL"] = TopAbs_SHELL;
+ aShapeTypes["SHELLS"] = TopAbs_SHELL;
+ aShapeTypes["FACE"] = TopAbs_FACE;
+ aShapeTypes["FACES"] = TopAbs_FACE;
+ aShapeTypes["WIRE"] = TopAbs_WIRE;
+ aShapeTypes["WIRES"] = TopAbs_WIRE;
+ aShapeTypes["EDGE"] = TopAbs_EDGE;
+ aShapeTypes["EDGES"] = TopAbs_EDGE;
+ aShapeTypes["VERTEX"] = TopAbs_VERTEX;
+ aShapeTypes["VERTICES"] = TopAbs_VERTEX;
}
- if (MyShapeTypes.find(theType) != MyShapeTypes.end())
- return MyShapeTypes[theType];
+ if (aShapeTypes.find(theType) != aShapeTypes.end())
+ return aShapeTypes[theType];
Events_InfoMessage("Model_SelectionNaming", "Shape type defined in XML is not implemented!").send();
return TopAbs_SHAPE;
}
bool aIsDisabled = theFeature->isDisabled();
if (!aIsDisabled) {
std::set<std::shared_ptr<ModelAPI_Feature> > aNewSet;
- if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated) {
+ if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated ||
+ theFeature->data()->execState() == ModelAPI_StateInvalidArgument) { // issue 1519
// do not forget that in this case all were the reasons
aNewSet.insert(theFeature);
} else {
TestUndoRedo.py
TestDocument.py
Test1064.py
- TestResults.py)
+ TestResults.py
+ Test1512.py)
template<class T1, class T2> std::shared_ptr<T1> shared_ptr_cast(std::shared_ptr<T2> theObject);
%template(featureToCompositeFeature) shared_ptr_cast<ModelAPI_CompositeFeature, ModelAPI_Feature>;
%template(objectToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_Object>;
+%template(objectToResult) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
%template(compositeFeatureToFeature) shared_ptr_cast<ModelAPI_Feature, ModelAPI_CompositeFeature>;
%template(modelAPI_Result) shared_ptr_cast<ModelAPI_Result, ModelAPI_Object>;
ModelAPI_ResultBody::ModelAPI_ResultBody()
: myBuilder(0)
{
+ myConnect = ConnectionNotComputed;
}
ModelAPI_ResultBody::~ModelAPI_ResultBody()
const bool theIsStoreSameShapes)
{
myBuilder->store(theShape, theIsStoreSameShapes);
+ myConnect = ConnectionNotComputed;
static Events_Loop* aLoop = Events_Loop::loop();
static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
const std::shared_ptr<GeomAPI_Shape>& theToShape)
{
myBuilder->storeGenerated(theFromShape, theToShape);
+ myConnect = ConnectionNotComputed;
static Events_Loop* aLoop = Events_Loop::loop();
static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
const int theDecomposeSolidsTag)
{
myBuilder->storeModified(theOldShape, theNewShape, theDecomposeSolidsTag);
+ myConnect = ConnectionNotComputed;
static Events_Loop* aLoop = Events_Loop::loop();
static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
void ModelAPI_ResultBody::storeWithoutNaming(const std::shared_ptr<GeomAPI_Shape>& theShape)
{
myBuilder->storeWithoutNaming(theShape);
+ myConnect = ConnectionNotComputed;
static Events_Loop* aLoop = Events_Loop::loop();
static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
{
myBuilder->loadDisconnectedVertexes(theShape, theName, theTag);
}
+
+bool ModelAPI_ResultBody::isConnectedTopology()
+{
+ if (myConnect == ConnectionNotComputed) {
+ myConnect = shape()->isConnectedTopology() ? IsConnected : IsNotConnected;
+ }
+ return myConnect == IsConnected;
+}
return RESULT_BODY_COLOR;
}
+ /// Iternal enumeration for storage the information of connected topology flag
+ enum ConnectedTopologyFlag {
+ ConnectionNotComputed, ///< not yet computed
+ IsConnected, ///< the topology is connected
+ IsNotConnected ///< the topology is connected
+ };
+ /// Keeps (not persistently) the connected topology flag
+ ConnectedTopologyFlag myConnect;
+
/// \brief Stores the shape (called by the execution method).
/// param[in] theShape shape to store.
/// param[in] theIsStoreSameShapes if false stores reference to the same shape if it is already in document.
// is equal to the given shape
MODELAPI_EXPORT virtual bool isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape) = 0;
+ /// Returns true is the topology is connected. Cashes this information for the current shape,
+ /// so it is more effective to use this method than directly GeomAPI_Shape.
+ MODELAPI_EXPORT virtual bool isConnectedTopology();
+
protected:
/// Default constructor accessible only from Model_Objects
MODELAPI_EXPORT ModelAPI_ResultBody();
return true;
DocumentPtr aRootDocument = aSession->moduleDocument();
if (aDocument != aRootDocument) {
- ResultPtr aPartResult = findPartResult(aRootDocument, aDocument);
- if (aPartResult.get()) {
- FeaturePtr aPartFeature;
- if (theSearcher.get()) // only if the relative search is needed
- aPartFeature = aRootDocument->feature(aPartResult);
- if (findVariable(aRootDocument, aPartFeature, theName, outValue, theParam))
- return true;
- }
+ // any parameters in PartSet is okindependently on the Part position (issu #1504)
+ if (findVariable(aRootDocument, FeaturePtr(), theName, outValue, theParam))
+ return true;
}
return false;
}
}
}
+//******************************************************************
+bool allDocumentsActivated(std::string& theNotActivatedNames)
+{
+ theNotActivatedNames = "";
+ bool anAllPartActivated = true;
+
+ DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+ int aSize = aRootDoc->size(ModelAPI_ResultPart::group());
+ for (int i = 0; i < aSize; i++) {
+ ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);
+ ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
+ if (!aPart->isActivated()) {
+ anAllPartActivated = false;
+ if (!theNotActivatedNames.empty())
+ theNotActivatedNames += ", ";
+ theNotActivatedNames += aObject->data()->name().c_str();
+ }
+ }
+ return anAllPartActivated;
+}
+
bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,
const bool theFlushRedisplay,
const bool theUseComposite,
}
} // namespace ModelAPI_Tools
-
-
*/
MODELAPI_EXPORT void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults);
+/*!
+ Returns true if there are no parts in the document, which are not activated
+ \param theNotActivatedNames out string which contains not activated names
+ \return a boolean value
+ */
+MODELAPI_EXPORT bool allDocumentsActivated(std::string& theNotActivatedNames);
+
/*! Removes features from the document
* \param theFeatures a list of features to be removed
--- /dev/null
+"""
+ Test1512.py
+ Unit test for testing the correct selection of feature by the faces after the BOPs applied
+
+"""
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+
+__updated__ = "2016-05-31"
+
+aSession = ModelAPI_Session.get()
+aPartSet = aSession.moduleDocument()
+
+#=========================================================================
+# Create a part
+#=========================================================================
+aSession.startOperation()
+aPartFeature = aPartSet.addFeature("Part")
+aSession.finishOperation()
+assert (len(aPartFeature.results()) == 1)
+aPart = aSession.activeDocument()
+
+#=========================================================================
+# Create a sketch rectangle in PartSet
+#=========================================================================
+aSession.startOperation()
+aSketchFeature = featureToCompositeFeature(aPart.addFeature("Sketch"))
+aXOYPlane = objectToResult(aPartSet.objectByName("Construction", "XOY"))
+aSketchFeature.selection("External").setValue(aXOYPlane, None)
+# Create lines
+aLine1 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine1.attribute("StartPoint")).setValue(0, 0)
+geomDataAPI_Point2D(aLine1.attribute("EndPoint")).setValue(200, 0)
+aLine2 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine2.attribute("StartPoint")).setValue(200, 0)
+geomDataAPI_Point2D(aLine2.attribute("EndPoint")).setValue(200, 100)
+aLine3 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine3.attribute("StartPoint")).setValue(200, 100)
+geomDataAPI_Point2D(aLine3.attribute("EndPoint")).setValue(0, 100)
+aLine4 = aSketchFeature.addFeature("SketchLine")
+geomDataAPI_Point2D(aLine4.attribute("StartPoint")).setValue(0, 100)
+geomDataAPI_Point2D(aLine4.attribute("EndPoint")).setValue(0, 0)
+aSession.finishOperation()
+
+#=========================================================================
+# Make extrusion on rectangle
+#=========================================================================
+aSession.startOperation()
+aBox = aPart.addFeature("Extrusion")
+aBox.selectionList("base").append(aSketchFeature.firstResult(), None)
+aBox.string("CreationMethod").setValue("BySizes")
+aBox.real("to_size").setValue(50)
+aBox.real("from_size").setValue(0)
+aSession.finishOperation()
+
+#=========================================================================
+# Create a cylindrical sketch for a big hole
+#=========================================================================
+aSession.startOperation()
+aSketchFeature2 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+aSketchFeature2.selection("External").setValue(aXOYPlane, None);
+aCirc1 = aSketchFeature2.addFeature("SketchCircle")
+geomDataAPI_Point2D(aCirc1.attribute("CircleCenter")).setValue(100, 50)
+aCirc1.real("CircleRadius").setValue(40)
+aSession.finishOperation()
+
+#=========================================================================
+# Make extrusion on a big circle
+#=========================================================================
+aSession.startOperation()
+aHoleExt = aPart.addFeature("Extrusion")
+aHoleExt.selectionList("base").append(aSketchFeature2.firstResult(), None)
+aHoleExt.string("CreationMethod").setValue("BySizes")
+aHoleExt.real("to_size").setValue(60)
+aHoleExt.real("from_size").setValue(0)
+aSession.finishOperation()
+
+#=========================================================================
+# Do cut a hole from a box
+#=========================================================================
+aSession.startOperation()
+aCut1 = aPart.addFeature("Boolean")
+aCut1.selectionList("main_objects").append(aBox.firstResult(), None)
+aCut1.selectionList("tool_objects").append(aHoleExt.firstResult(), None)
+aCut1.integer("bool_type").setValue(0) # cut
+aSession.finishOperation()
+
+#=========================================================================
+# Create a cylindrical sketch for a small tower
+#=========================================================================
+aSession.startOperation()
+aSketchFeature3 = featureToCompositeFeature(aPart.addFeature("Sketch"))
+aSketchFeature3.selection("External").setValue(aXOYPlane, None);
+aCirc2 = aSketchFeature3.addFeature("SketchCircle")
+geomDataAPI_Point2D(aCirc2.attribute("CircleCenter")).setValue(20, 20)
+aCirc2.real("CircleRadius").setValue(10)
+aSession.finishOperation()
+
+#=========================================================================
+# Make extrusion on a small circle
+#=========================================================================
+aSession.startOperation()
+aTower = aPart.addFeature("Extrusion")
+aTower.selectionList("base").append(aSketchFeature3.firstResult(), None)
+aTower.string("CreationMethod").setValue("BySizes")
+aTower.real("to_size").setValue(100)
+aTower.real("from_size").setValue(0)
+aSession.finishOperation()
+
+#=========================================================================
+# Do fuse with a tower. Tower must be an argument (not tool) to add the problem to the faces owners detection.
+#=========================================================================
+aSession.startOperation()
+aFuse = aPart.addFeature("Boolean")
+aFuse.selectionList("main_objects").append(aTower.firstResult(), None)
+aFuse.selectionList("tool_objects").append(aCut1.firstResult(), None)
+aFuse.integer("bool_type").setValue(1) # fuse
+aSession.finishOperation()
+
+#=========================================================================
+# Create a group feature to use the selection attribute for selection of faces by the name.
+#=========================================================================
+def check_owner(selection, topology_type, feature):
+ aSession.startOperation()
+ aGroup = aPart.addFeature("Group")
+ aGroup.selectionList("group_list").append(selection, topology_type)
+ aFace = aGroup.selectionList("group_list").value(0).value()
+ aTestFeature = aPart.producedByFeature(aFuse.firstResult(), aFace)
+ assert(aTestFeature.name() == feature.name())
+ aSession.abortOperation()
+
+# check faces
+check_owner("Extrusion_1_1/Generated_Face_1", "face", aBox)
+check_owner("Boolean_2_1/Modified_3", "face", aBox)
+check_owner("Boolean_1_1/Modified_1", "face", aHoleExt)
+check_owner("Boolean_2_1/Modified_2", "face", aTower)
+# check edges without ambiguity
+check_owner("Boolean_2_1/Modified_3&Extrusion_1_1/Generated_Face_2", "edge", aBox)
+check_owner("Boolean_2_1/Modified_2&Extrusion_3_1/To_Face_1_1", "edge", aTower)
+
+# check the connected topology method: solid is not a compound of connected topology
+assert(aFuse.firstResult().shape().isConnectedTopology() == False)
+
+#=========================================================================
+# End of test
+#=========================================================================
ModuleBase_WidgetValidator.h
ModuleBase_IconFactory.h
ModuleBase_Dialog.h
+ ModuleBase_ModelDialogWidget.h
)
SET(PROJECT_SOURCES
#include "ModuleBase_IWorkshop.h"
#include "ModuleBase_IPropertyPanel.h"
#include "ModuleBase_PageWidget.h"
+#include "ModuleBase_ModelDialogWidget.h"
#include <ModelAPI_Session.h>
#include <ModelAPI_Events.h>
aFactory.createWidget(aPage, false);
myWidgets = aFactory.getModelWidgets();
- foreach (ModuleBase_ModelWidget* aWidget, myWidgets) {
- initializeWidget(aWidget);
- }
QFrame* aFrame = new QFrame(this);
aFrame->setFrameStyle(QFrame::WinPanel | QFrame::Raised);
QVBoxLayout* aBtnLayout = new QVBoxLayout(aFrame);
ModuleBase_Tools::adjustMargins(aBtnLayout);
- QDialogButtonBox* aBtnBox = new QDialogButtonBox(
+ myButtonsBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, aFrame);
- aBtnLayout->addWidget(aBtnBox);
+ aBtnLayout->addWidget(myButtonsBox);
+
+ myButtonsBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":pictures/button_ok.png"));
+ myButtonsBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":pictures/button_cancel.png"));
- aBtnBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":pictures/button_ok.png"));
- aBtnBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":pictures/button_cancel.png"));
+ connect(myButtonsBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(myButtonsBox, SIGNAL(rejected()), this, SLOT(reject()));
- connect(aBtnBox, SIGNAL(accepted()), this, SLOT(accept()));
- connect(aBtnBox, SIGNAL(rejected()), this, SLOT(reject()));
+ foreach (ModuleBase_ModelWidget* aWidget, myWidgets) {
+ initializeWidget(aWidget);
+ }
}
void ModuleBase_Dialog::initializeWidget(ModuleBase_ModelWidget* theWidget)
{
+ ModuleBase_ModelDialogWidget* aDlgWgt = dynamic_cast<ModuleBase_ModelDialogWidget*>(theWidget);
+ if (aDlgWgt)
+ aDlgWgt->setDialogButtons(myButtonsBox);
+
theWidget->setFeature(myFeature);
theWidget->restoreValue();
}
class ModuleBase_IWorkshop;
class ModuleBase_ModelWidget;
+class QDialogButtonBox;
+
/**
* \ingroup GUI
/// Redefinition of virtual method
virtual void showEvent(QShowEvent* theEvent);
-
private:
/// Initialising of the widget
void initializeWidget(ModuleBase_ModelWidget* theWidget);
/// Pointer on active widget
ModuleBase_ModelWidget* myActiveWidget;
+
+ /// Buttons of the dialog
+ QDialogButtonBox* myButtonsBox;
};
#endif
#include <ModuleBase_WidgetValidated.h>
#include <ModuleBase_WidgetValidator.h>
#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
IMPLEMENT_STANDARD_HANDLE(ModuleBase_FilterValidated, SelectMgr_Filter);
IMPLEMENT_STANDARD_RTTIEXT(ModuleBase_FilterValidated, SelectMgr_Filter);
+//#define DEBUG_CURRENT_SELECTION
+
Standard_Boolean ModuleBase_FilterValidated::IsOk(const Handle(SelectMgr_EntityOwner)& theOwner) const
{
bool aValid = true;
ModuleBase_Operation* anOperation = myWorkshop->module()->currentOperation();
if (anOperation) {
+#ifdef DEBUG_CURRENT_SELECTION
+ QString aPrefix = "ModuleBase_FilterValidated::IsOk: ";
+ QList<ModuleBase_ViewerPrsPtr> aSelected = myWorkshop->selection()->getSelected(ModuleBase_ISelection::Viewer);
+ QList<ModuleBase_ViewerPrsPtr>::const_iterator anIt = aSelected.begin(), aLast = aSelected.end();
+ QStringList anInfo;
+ ModuleBase_ViewerPrsPtr aPrs;
+ for (; anIt != aLast; anIt++) {
+ aPrs = (*anIt);
+ if (!aPrs.get())
+ continue;
+
+ //GeomShapePtr aShape = aPrs->shape();
+ ObjectPtr anObject = aPrs->object();
+ QString anObjectInfo = anObject.get() ? ModuleBase_Tools::objectInfo(anObject) : "";
+ anInfo.append(anObjectInfo);
+ }
+ QString anInfoStr = anInfo.join(";\t");
+ qDebug(QString("%1: %2, %3").arg(aPrefix).arg(anInfo.size()).arg(anInfoStr).toStdString().c_str());
+#endif
+
ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
ModuleBase_ModelWidget* aCurrentWidget = aPanel->preselectionWidget();
if (!aCurrentWidget)
/// \param theObject a model object\r
virtual bool canActivateSelection(const ObjectPtr& theObject) const;\r
\r
- /// Returns true if the given selection mode can be activated for the given presentgation\r
- /// \param theIO an object presentation\r
- /// \param theMode selection mode\r
- virtual bool canActivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const { return true; }\r
-\r
- /// Returns true if the given selection mode must be deactivated for the given presentgation in any case\r
- /// \param theIO an object presentation\r
- /// \param theMode selection mode\r
- virtual bool needDeactivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const { return false; }\r
-\r
/// Reacts to the delete action in module\r
/// \returns true if the action is processed\r
virtual bool deleteObjects() { return false; };\r
/// \param theModes a list of modes\r
virtual void activeSelectionModes(QIntList& theModes) {}\r
\r
+ /// Appends specific selection modes for the module to the list of types\r
+ /// \param theTypes a selection modes to be extended\r
+ virtual void customSubShapesSelectionModes(QIntList& theTypes) {}\r
+\r
/// Activate custom presentation for the object. Default realization is empty.\r
/// \param theFeature a feature instance\r
/// \param theFlag a flag of level of customization, which means that only part of sub-elements\r
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModuleBase_ModelDialogWidget.h
+// Created: 01 June 2016
+// Author: Vitaly SMETANNIKOV
+
+#ifndef MODULEBASE_MODELDIALOGWIDGET_H
+#define MODULEBASE_MODELDIALOGWIDGET_H
+
+#include "ModuleBase.h"
+#include "ModuleBase_ModelWidget.h"
+
+class QDialogButtonBox;
+
+class MODULEBASE_EXPORT ModuleBase_ModelDialogWidget : public ModuleBase_ModelWidget
+{
+Q_OBJECT
+public:
+ /// Constructor
+ /// \param theParent the parent object
+ /// \param theData the widget configuration. The attribute of the model widget is obtained from
+ /// a low-level API for reading xml definitions of widgets
+ ModuleBase_ModelDialogWidget(QWidget* theParent, const Config_WidgetAPI* theData) :
+ ModuleBase_ModelWidget(theParent, theData) {}
+
+ /// Set general buttons from dialog
+ /// \param theButtons the dialog buttons
+ void setDialogButtons(QDialogButtonBox* theButtons) { myOkCancelBtn = theButtons; }
+
+protected:
+
+ /// Contains dialog buttons to enable/disable Ok and Cancel buttons
+ QDialogButtonBox* myOkCancelBtn;
+};
+
+#endif
\ No newline at end of file
//#define DEBUG_VALUE_STATE
+//#define DEBUG_WIDGET_INSTANCE
+
ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
const Config_WidgetAPI* theData)
: QWidget(theParent),
myFlushUpdateBlocked(false),
myWidgetValidator(0)
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::ModuleBase_ModelWidget");
+#endif
+
myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
myDefaultValue = theData->getProperty(ATTR_DEFAULT);
connect(this, SIGNAL(valuesModified()), this, SLOT(onWidgetValuesModified()));
}
+ModuleBase_ModelWidget::~ModuleBase_ModelWidget()
+{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::~ModuleBase_ModelWidget");
+#endif
+}
+
bool ModuleBase_ModelWidget::reset()
{
bool aResult = resetCustom();
return theObject->data()->attribute(attributeID())->isInitialized();
}
+void ModuleBase_ModelWidget::processValueState()
+{
+ if (myState == ModifiedInPP || myState == ModifiedInViewer)
+ storeValue();
+}
+
QString ModuleBase_ModelWidget::getValueStateError() const
{
QString anError = "";
bool ModuleBase_ModelWidget::focusTo()
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::focusTo");
+#endif
QList<QWidget*> aControls = getControls();
QList<QWidget*>::const_iterator anIt = aControls.begin(), aLast = aControls.end();
bool isFocusAccepted = false;
void ModuleBase_ModelWidget::activate()
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::activate");
+#endif
// the control value is stored to the mode by the focus in on the widget
// we need the value is initialized in order to enable the apply button in the property panel.
// It should happens in the creation mode only because all fields are filled in the edition mode
void ModuleBase_ModelWidget::deactivate()
{
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::deactivate");
+#endif
myIsValueStateBlocked = false;
- if (myState == ModifiedInPP || myState == ModifiedInViewer)
- storeValue();
myState = Stored;
-
if (myWidgetValidator)
myWidgetValidator->activateFilters(false);
}
void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject)
{
if (!myFlushUpdateBlocked) {
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::updateObject");
+#endif
ModuleBase_Tools::flushUpdated(theObject);
emit objectUpdated();
}
void ModuleBase_ModelWidget::moveObject(ObjectPtr theObj)
{
//blockUpdateViewer(true);
+#ifdef DEBUG_WIDGET_INSTANCE
+ qDebug("ModuleBase_ModelWidget::moveObject");
+#endif
static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
ModelAPI_EventCreator::get()->sendUpdated(theObj, anEvent);
/// a low-level API for reading xml definitions of widgets
ModuleBase_ModelWidget(QWidget* theParent, const Config_WidgetAPI* theData);
/// Destructor
- virtual ~ModuleBase_ModelWidget()
- {
- }
+ virtual ~ModuleBase_ModelWidget();
/// Fills the widget with default values. It calls the resetCustom method and change
/// the widget state to Reset if the reset is performed.
/// \return the enumeration result
ValueState getValueState() const { return myState; }
+ /// Stores the widget value if it is modified
+ void processValueState();
+
/// Returns an attribute error according to the value state
/// It exists in all cases excepring the "Store" case
QString getValueStateError() const;
#include <ModelAPI_AttributeRefList.h>
#endif
+//#define DEBUG_OPERATION_START
+
#ifdef _DEBUG
#include <QDebug>
#endif
bool ModuleBase_OperationFeature::start()
{
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::start -- begin");
+#endif
setIsModified(false);
QString anId = getDescription()->operationId();
if (myIsEditing) {
// in order to update commands status in the workshop, to be exact the feature action
// to be unchecked
abort();
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::start -- end : IMPOSSIBLE to start");
+#endif
return false;
}
}
//Already called startOperation();
emit started();
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::start -- end");
+#endif
return true;
}
void ModuleBase_OperationFeature::abort()
{
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::abort -- begin");
+#endif
+
emit beforeAborted();
// the viewer update should be blocked in order to avoid the features blinking before they are
Events_Loop::loop()->send(aMsg);
emit aborted();
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::abort -- end");
+#endif
}
bool ModuleBase_OperationFeature::commit()
{
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::commit -- begin");
+#endif
ModuleBase_IPropertyPanel* aPanel = propertyPanel();
if (aPanel) {
ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
emit committed();
afterCommitOperation();
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::commit -- end : IMPOSSIBLE to commit");
+#endif
return true;
}
+#ifdef DEBUG_OPERATION_START
+ qDebug("ModuleBase_OperationFeature::commit -- end");
+#endif
return false;
}
aWgt = (*aWIt);
if (aWgt->attributeID() == theGreedAttributeId) {
aPropertyPanel->setPreselectionWidget(aWgt);
- aWgt->setSelection(myPreSelection, true);
- aPropertyPanel->setPreselectionWidget(NULL);
- aFilledWgt = aWgt;
- break;
+ if (aWgt->setSelection(myPreSelection, true)) {
+ aPropertyPanel->setPreselectionWidget(NULL);
+ aFilledWgt = aWgt;
+ break;
+ }
+ else { // do not process invalid for greed widget selection
+ break;
+ }
}
}
}
if (!aWgt->canAcceptFocus())
continue;
aPropertyPanel->setPreselectionWidget(aWgt);
- if (!aWgt->setSelection(myPreSelection, true)) {
+ if (myPreSelection.empty() || !aWgt->setSelection(myPreSelection, true)) {
isSet = false;
break;
} else {
Set(myOriginalShape);
}
// change deviation coefficient to provide more precise circle
- ModuleBase_Tools::setDefaultDeviationCoefficient(Shape(), Attributes());
+ ModuleBase_Tools::setDefaultDeviationCoefficient(myResult, Attributes());
AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
if (!aReadyToDisplay) {
#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_AttributeRefAttrList.h>
#include <ModelAPI_ResultPart.h>
+#include <ModelAPI_ResultConstruction.h>
#include <Events_Loop.h>
#include <ModelAPI_Data.h>
#include <GeomDataAPI_Point2D.h>
#include <Events_InfoMessage.h>
+#include <GeomAPI_ShapeExplorer.h>
#include <Config_PropManager.h>
#include <string>
const double tolerance = 1e-7;
+const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
//#define DEBUG_ACTIVATE_WINDOW
//#define DEBUG_SET_FOCUS
+//#define DEBUG_SELECTION_INFO
+
+#ifdef DEBUG_SELECTION_INFO
+#include <ModuleBase_ISelection.h>
+#include <ModuleBase_ViewerPrs.h>
+
+#include <AIS_InteractiveContext.hxx>
+#include <AIS_ListOfInteractive.hxx>
+#include <AIS_ListIteratorOfListOfInteractive.hxx>
+#include <AIS_Shape.hxx>
+#include <TopoDS_Shape.hxx>
+#include <AIS_LocalContext.hxx>
+#include <NCollection_List.hxx>
+#include <StdSelect_BRepOwner.hxx>
+#include <TColStd_ListOfInteger.hxx>
+#include <TColStd_ListIteratorOfListOfInteger.hxx>
+#endif
namespace ModuleBase_Tools {
else {
QGraphicsEffect* anEffect = theWidget->graphicsEffect();
if(anEffect)
- anEffect->deleteLater();
+ anEffect->deleteLater();
theWidget->setGraphicsEffect(NULL);
}
}
if (aFeature.get()) {
aFeatureStr.append(QString(": %1").arg(aFeature->getKind().c_str()).toStdString().c_str());
if (aFeature->data()->isValid()) {
- aFeatureStr.append(QString(", name=%1").arg(aFeature->data()->name().c_str()).toStdString()
+ aFeatureStr.append(QString(", name=%1").arg(theObj->data()->name().c_str()).toStdString()
.c_str());
}
if (isUseAttributesInfo) {
return aFeatureStr;
}
+#ifdef DEBUG_SELECTION_INFO
+QString getShapeTypeInfo(const int theType)
+{
+ QString anInfo = "Undefined";
+ switch(theType) {
+ case TopAbs_COMPOUND: anInfo = "compound"; break;
+ case TopAbs_COMPSOLID: anInfo = "compsolid"; break;
+ case TopAbs_SOLID: anInfo = "solid"; break;
+ case TopAbs_SHELL: anInfo = "shell"; break;
+ case TopAbs_FACE: anInfo = "face"; break;
+ case TopAbs_WIRE: anInfo = "wire"; break;
+ case TopAbs_EDGE: anInfo = "edge"; break;
+ case TopAbs_VERTEX: anInfo = "vertex"; break;
+ case TopAbs_SHAPE: anInfo = "shape"; break;
+ default: break;
+ }
+ return anInfo;
+}
+
+QString getModeInfo(const int theMode)
+{
+ QString anInfo = "Undefined";
+ switch(theMode) {
+ case 0: anInfo = "SHAPE(0)"; break;
+ case 1: anInfo = "VERTEX(1)"; break;
+ case 2: anInfo = "EDGE(2)"; break;
+ case 3: anInfo = "WIRE(3)"; break;
+ case 4: anInfo = "FACE(4)"; break;
+ case 5: anInfo = "SHELL(5)"; break;
+ case 6: anInfo = "SOLID(6)"; break;
+ case 7: anInfo = "COMPSOLID(7)"; break;
+ case 8: anInfo = "COMPOUND(8)"; break;
+ case 100: anInfo = "Sel_Mode_First(100)"; break; //SketcherPrs_Tools
+ case 101: anInfo = "Sel_Constraint(101)"; break;
+ case 102: anInfo = "Sel_Dimension_All(102)"; break;
+ case 103: anInfo = "Sel_Dimension_Line(103)"; break;
+ case 104: anInfo = "Sel_Dimension_Text(104)"; break;
+ default: break;
+ }
+ return anInfo;
+}
+
+QString displayedInteractiveObjects(Handle(AIS_InteractiveContext)& theContext,
+ const bool theShapeInfoOnly = true)
+{
+ if (theContext.IsNull())
+ return "";
+ AIS_ListOfInteractive aListOfIO;
+ theContext->DisplayedObjects(aListOfIO, false);
+ QStringList anObjects;
+ AIS_ListIteratorOfListOfInteractive aIt;
+ for (aIt.Initialize(aListOfIO); aIt.More(); aIt.Next()) {
+ Handle(AIS_InteractiveObject) anAISIO = aIt.Value();
+ Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISIO);
+ if (theShapeInfoOnly && aShapePrs.IsNull())
+ continue;
+
+ QString anInfo = "IO";
+ std::ostringstream aPtrStr;
+ aPtrStr << "[" << anAISIO.Access() << "]";
+ anInfo += aPtrStr.str().c_str();
+
+ if (!aShapePrs.IsNull()) {
+ const TopoDS_Shape& aShape = aShapePrs->Shape();
+ if (aShape.IsNull())
+ Events_Error::throwException("An empty AIS presentation");
+ else
+ anInfo += QString(", shape type: %1").arg(getShapeTypeInfo(aShape.ShapeType()));
+ }
+ TColStd_ListOfInteger aTColModes;
+ theContext->ActivatedModes(anAISIO, aTColModes);
+ TColStd_ListIteratorOfListOfInteger itr( aTColModes );
+ QIntList aModesActivatedForIO;
+ bool isDeactivated = false;
+ QStringList aModes;
+ for (; itr.More(); itr.Next() ) {
+ Standard_Integer aMode = itr.Value();
+ aModes.append(getModeInfo(aMode));
+ //int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
+ }
+ if (aModes.size() > 0)
+ anInfo += QString(", activated modes: %1").arg(aModes.join(", "));
+
+ anObjects += anInfo;
+ }
+ QString aValue = QString("displayedIO[%1]").arg(anObjects.size());
+ if (anObjects.size() > 0)
+ aValue += QString(":\n %1").arg(anObjects.join("\n "));
+ return aValue;
+}
+
+QString activeOwners(Handle(AIS_InteractiveContext)& theContext, const bool theShapeInfoOnly = true)
+{
+ if (theContext.IsNull())
+ return "";
+ Handle(AIS_LocalContext) aLContext = theContext->LocalContext();
+ TCollection_AsciiString aSelectionName = aLContext->SelectionName();
+ aLContext->UnhilightPicked(Standard_False);
+
+ NCollection_List<Handle(SelectBasics_EntityOwner)> anActiveOwners;
+ aLContext->MainSelector()->ActiveOwners(anActiveOwners);
+ NCollection_List<Handle(SelectBasics_EntityOwner)>::Iterator anOwnersIt (anActiveOwners);
+ Handle(SelectMgr_EntityOwner) anOwner;
+ QStringList anObjects;
+ for (; anOwnersIt.More(); anOwnersIt.Next()) {
+ anOwner = Handle(SelectMgr_EntityOwner)::DownCast (anOwnersIt.Value());
+ Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+ if (theShapeInfoOnly && BROwnr.IsNull())
+ continue;
+
+ QString anInfo = "Owner";
+ std::ostringstream aPtrStr;
+ aPtrStr << "[" << anOwner.Access() << "]";
+ anInfo += aPtrStr.str().c_str();
+
+ Handle(AIS_InteractiveObject) aAISObj =
+ Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
+ if (!aAISObj.IsNull()) {
+ std::ostringstream aPtrStr;
+ aPtrStr << "[" << aAISObj.Access() << "]";
+ anInfo += QString(", selectable(IO): %1").arg(aPtrStr.str().c_str());
+ }
+
+ if (!BROwnr.IsNull() && BROwnr->HasShape()) {
+ const TopoDS_Shape& aShape = BROwnr->Shape();
+ if (aShape.IsNull())
+ Events_Error::throwException("An empty AIS presentation");
+ else
+ anInfo += QString(", shape type: %1").arg(getShapeTypeInfo(aShape.ShapeType()));
+ }
+ anObjects += anInfo;
+ }
+ QString aValue = QString("activeOwners[%1]").arg(anObjects.size());
+ if (anObjects.size() > 0)
+ aValue += QString(":\n %1").arg(anObjects.join("\n "));
+ return aValue;
+}
+
+QString selectedOwners(Handle(AIS_InteractiveContext)& theContext, const bool theShapeInfoOnly = true)
+{
+ QStringList anObjects;
+ if (theContext.IsNull())
+ return "";
+
+ QList<long> aSelectedIds; // Remember of selected address in order to avoid duplicates
+ for (theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected()) {
+ Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
+ Handle(StdSelect_BRepOwner) BROwnr = Handle(StdSelect_BRepOwner)::DownCast(anOwner);
+ if (theShapeInfoOnly && BROwnr.IsNull())
+ continue;
+
+ if (aSelectedIds.contains((long)anOwner.Access()))
+ continue;
+ aSelectedIds.append((long)anOwner.Access());
+
+ QString anInfo = "Owner";
+ std::ostringstream aPtrStr;
+ aPtrStr << "[" << anOwner.Access() << "]";
+ anInfo += aPtrStr.str().c_str();
+
+ if (!BROwnr.IsNull() && BROwnr->HasShape()) {
+ const TopoDS_Shape& aShape = BROwnr->Shape();
+ anInfo += QString(", shape type = %1").arg(getShapeTypeInfo(aShape.ShapeType()));
+ }
+ anObjects += anInfo;
+ }
+ QString aValue = QString("selectedOwners[%1]").arg(anObjects.size());
+ if (anObjects.size() > 0)
+ aValue += QString(":\n %1").arg(anObjects.join("\n "));
+ return aValue;
+}
+#endif
+
+void selectionInfo(Handle(AIS_InteractiveContext)& theContext, const std::string& thePrefix)
+{
+#ifdef DEBUG_SELECTION_INFO
+ QString aValue = QString("\n\n\nDEBUG_SELECTION_INFO for '%1'\n%2\n%3\n%4")
+ .arg(thePrefix.c_str())
+ .arg(displayedInteractiveObjects(theContext))
+ .arg(activeOwners(theContext))
+ .arg(selectedOwners(theContext));
+ qDebug(aValue.toStdString().c_str());
+#endif
+}
+
typedef QMap<QString, TopAbs_ShapeEnum> ShapeTypes;
-static ShapeTypes MyShapeTypes;
+static ShapeTypes myShapeTypes;
TopAbs_ShapeEnum shapeType(const QString& theType)
{
- if (MyShapeTypes.count() == 0) {
- MyShapeTypes["face"] = TopAbs_FACE;
- MyShapeTypes["faces"] = TopAbs_FACE;
- MyShapeTypes["vertex"] = TopAbs_VERTEX;
- MyShapeTypes["vertices"] = TopAbs_VERTEX;
- MyShapeTypes["wire"] = TopAbs_WIRE;
- MyShapeTypes["wires"] = TopAbs_WIRE;
- MyShapeTypes["edge"] = TopAbs_EDGE;
- MyShapeTypes["edges"] = TopAbs_EDGE;
- MyShapeTypes["shell"] = TopAbs_SHELL;
- MyShapeTypes["solid"] = TopAbs_SOLID;
- MyShapeTypes["solids"] = TopAbs_SOLID;
- MyShapeTypes["objects"] = TopAbs_SHAPE;
+ if (myShapeTypes.count() == 0) {
+ myShapeTypes["compound"] = TopAbs_COMPOUND;
+ myShapeTypes["compounds"] = TopAbs_COMPOUND;
+ myShapeTypes["compsolid"] = TopAbs_COMPSOLID;
+ myShapeTypes["compsolids"] = TopAbs_COMPSOLID;
+ myShapeTypes["solid"] = TopAbs_SOLID;
+ myShapeTypes["solids"] = TopAbs_SOLID;
+ myShapeTypes["shell"] = TopAbs_SHELL;
+ myShapeTypes["shells"] = TopAbs_SHELL;
+ myShapeTypes["face"] = TopAbs_FACE;
+ myShapeTypes["faces"] = TopAbs_FACE;
+ myShapeTypes["wire"] = TopAbs_WIRE;
+ myShapeTypes["wires"] = TopAbs_WIRE;
+ myShapeTypes["edge"] = TopAbs_EDGE;
+ myShapeTypes["edges"] = TopAbs_EDGE;
+ myShapeTypes["vertex"] = TopAbs_VERTEX;
+ myShapeTypes["vertices"] = TopAbs_VERTEX;
+ myShapeTypes["objects"] = TopAbs_SHAPE;
}
QString aType = theType.toLower();
- if (MyShapeTypes.contains(aType))
- return MyShapeTypes[aType];
+ if(myShapeTypes.contains(aType))
+ return myShapeTypes[aType];
Events_InfoMessage("ModuleBase_Tools", "Shape type defined in XML is not implemented!").send();
return TopAbs_SHAPE;
}
}
}
+bool setDefaultDeviationCoefficient(std::shared_ptr<GeomAPI_Shape> theGeomShape)
+{
+ if (!theGeomShape.get())
+ return false;
+ // if the shape could not be exploded on faces, it contains only wires, edges, and vertices
+ // correction of deviation for them should not influence to the application performance
+ GeomAPI_ShapeExplorer anExp(theGeomShape, GeomAPI_Shape::FACE);
+ bool anEmpty = anExp.empty();
+ return !anExp.more();
+}
+
+void setDefaultDeviationCoefficient(const std::shared_ptr<ModelAPI_Result>& theResult,
+ const Handle(Prs3d_Drawer)& theDrawer)
+{
+ if (!theResult.get())
+ return;
+ bool aUseDeviation = false;
+
+ std::string aResultGroup = theResult->groupName();
+ if (aResultGroup == ModelAPI_ResultConstruction::group())
+ aUseDeviation = true;
+ else if (aResultGroup == ModelAPI_ResultBody::group()) {
+ GeomShapePtr aGeomShape = theResult->shape();
+ if (aGeomShape.get())
+ aUseDeviation = setDefaultDeviationCoefficient(aGeomShape);
+ }
+ if (aUseDeviation)
+ theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
+}
+
void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
const Handle(Prs3d_Drawer)& theDrawer)
{
if (theShape.IsNull())
return;
- TopAbs_ShapeEnum aType = theShape.ShapeType();
- if ((aType == TopAbs_EDGE) || (aType == TopAbs_WIRE))
- theDrawer->SetDeviationCoefficient(1.e-4);
+
+ std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape());
+ aGeomShape->setImpl(new TopoDS_Shape(theShape));
+ if (setDefaultDeviationCoefficient(aGeomShape))
+ theDrawer->SetDeviationCoefficient(DEFAULT_DEVIATION_COEFFICIENT);
}
Quantity_Color color(const std::string& theSection,
return isSub;
}
+//**************************************************************
+ResultPtr firstResult(const ObjectPtr& theObject)
+{
+ ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+ if (!aResult.get()) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+ if (aFeature.get())
+ aResult = aFeature->firstResult();
+ }
+ return aResult;
+}
+
//**************************************************************
bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
{
return aFirstResult->groupName() == theGroupOfResult;
}
+//**************************************************************
+bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
+{
+ bool aFoundModuleDocumentObject = false;
+ DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
+
+ std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
+ for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
+ FeaturePtr aFeature = *anIt;
+ ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
+ if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
+ continue;
+ aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
+ }
+
+ return aFoundModuleDocumentObject;
+}
+
//**************************************************************
bool askToDelete(const std::set<FeaturePtr> theFeatures,
const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
QWidget* theParent,
std::set<FeaturePtr>& theReferencesToDelete)
{
+ QString aNotActivatedDocWrn;
+ std::string aNotActivatedNames;
+ 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")
+ .arg(aNotActivatedNames.c_str());
+ }
+
std::set<FeaturePtr> aFeaturesRefsTo;
std::set<FeaturePtr> aFeaturesRefsToParameter;
std::set<FeaturePtr> aParameterFeatures;
+ QStringList aPartFeatureNames;
std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
aLast = theFeatures.end();
// separate features to references to parameter features and references to others
if (theReferences.find(aFeature) == theReferences.end())
continue;
+ if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
+ aPartFeatureNames.append(aFeature->name().c_str());
+
std::set<FeaturePtr> aRefFeatures;
std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
}
}
aParamFeatureNames.sort();
- QStringList aPartFeatureNames, anOtherFeatureNames;
+ QStringList anOtherFeatureNames;
anIt = theReferencesToDelete.begin();
aLast = theReferencesToDelete.end();
for (; anIt != aLast; anIt++) {
QString aSep = ", ";
if (!aPartFeatureNames.empty())
aText += QString(QObject::tr("The following parts will be deleted: %1.\n")).arg(aPartFeatureNames.join(aSep));
+ if (!aNotActivatedDocWrn.isEmpty())
+ aText += aNotActivatedDocWrn;
if (!anOtherFeatureNames.empty())
aText += QString(QObject::tr("Selected features are used in the following features: %1.\nThese features will be deleted.\n"))
.arg(anOtherFeatureNames.join(aSep));
#include <map>
+class Handle_AIS_InteractiveContext;
+
class QWidget;
class QLayout;
class QDoubleSpinBox;
namespace ModuleBase_Tools {
-/*
- * Methods to adjust margins and spacings.
- */
+/// Methods to adjust margins and spacings.
MODULEBASE_EXPORT void adjustMargins(QWidget* theWidget);
MODULEBASE_EXPORT void adjustMargins(QLayout* theLayout);
MODULEBASE_EXPORT void zeroMargins(QWidget* theWidget);
MODULEBASE_EXPORT void zeroMargins(QLayout* theLayout);
-/*
- * Calls the same-named Qt method for the given widget.
- * It sets the top-level widget containing this widget to be the active window.
- * An active window is a visible top-level window that has the keyboard input focus.
- * \param theWidget a widget to be activated
- * \param theIndo a debug information
- */
+/// Calls the same-named Qt method for the given widget.
+/// It sets the top-level widget containing this widget to be the active window.
+/// An active window is a visible top-level window that has the keyboard input focus.
+/// \param theWidget a widget to be activated
+/// \param theIndo a debug information
MODULEBASE_EXPORT void activateWindow(QWidget* theWidget, const QString& theInfo = QString());
-/*
- * Calls the same-named Qt method for the given widget.
- * Gives the keyboard input focus to this widget (or its focus proxy) if this widget or
- * one of its parents is the active window.
- * \param theWidget a widget to be activated
- * \param theIndo a debug information
- */
+/// Calls the same-named Qt method for the given widget.
+/// Gives the keyboard input focus to this widget (or its focus proxy) if this widget or
+/// one of its parents is the active window.
+/// \param theWidget a widget to be activated
+/// \param theIndo a debug information
MODULEBASE_EXPORT void setFocus(QWidget* theWidget, const QString& theInfo = QString());
-//! Sets or removes the shadow effect to the widget
-//! \param theWidget a widget to be styled
-//! \param isSetEffect if true, the shadow effect is set, overwise cleared
-//! \return resulting pixmap
+/// Sets or removes the shadow effect to the widget
+/// \param theWidget a widget to be styled
+/// \param isSetEffect if true, the shadow effect is set, overwise cleared
+/// \return resulting pixmap
MODULEBASE_EXPORT void setShadowEffect(QWidget* theWidget, const bool isSetEffect);
-/**
- * \ingroup GUI
- * Methods to modify a resource pixmap
- */
+/// \ingroup GUI
+/// Methods to modify a resource pixmap
-//! Create composite pixmap.
-//! Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates
-//! specified relatively to the upper left corner of \a theIcon.
+/// Create composite pixmap.
+/// Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates
+/// specified relatively to the upper left corner of \a theIcon.
-//! \param theAdditionalIcon resource text of the additional pixmap
-//! \param theIcon resource text of the background pixmap
-//! \return resulting pixmap
+/// \param theAdditionalIcon resource text of the additional pixmap
+/// \param theIcon resource text of the background pixmap
+/// \return resulting pixmap
MODULEBASE_EXPORT QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon);
-//! Generates the pixmap lighter than the resources pixmap.
-//! Pixmap \a theIcon is lighted according to the given value.
-//! If the lighter value is greater than 100, this functions returns a lighter pixmap.
-//! Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100,
-//! the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified.
+/// Generates the pixmap lighter than the resources pixmap.
+/// Pixmap \a theIcon is lighted according to the given value.
+/// If the lighter value is greater than 100, this functions returns a lighter pixmap.
+/// Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100,
+/// the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified.
-//! \param resource text of the pixmap
-//! \param theLighterValue a lighter factor
-//! \return resulting pixmap
+/// \param resource text of the pixmap
+/// \param theLighterValue a lighter factor
+/// \return resulting pixmap
MODULEBASE_EXPORT QPixmap lighter(const QString& theIcon, const int theLighterValue = 200);
/// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
/// \return a string
MODULEBASE_EXPORT QString objectInfo(const ObjectPtr& theObj, const bool isUseAttributesInfo = false);
+/// Converts the AIS context information in a string information.
+/// \param theContext a viewer context
+/// \param thePrefix additional information where the method is called
+MODULEBASE_EXPORT void selectionInfo(Handle_AIS_InteractiveContext& theContext,
+ const std::string& thePrefix);
+
/// Converts string value (name of shape type) to shape enum value
/// \param theType - string with shape type name
/// \return TopAbs_ShapeEnum value
/// \return boolean result
MODULEBASE_EXPORT bool isSubResult(ObjectPtr theObject);
-/*!
-Check types of objects which are in the given list
-\param theObjects the list of objects
-\param hasResult will be set to true if list contains Result objects
-\param hasFeature will be set to true if list contains Feature objects
-\param hasParameter will be set to true if list contains Parameter objects
-\param hasCompositeOwner will be set to true if list contains Sub-Feature objects
-*/
+/// Check types of objects which are in the given list
+/// \param theObjects the list of objects
+/// \param hasResult will be set to true if list contains Result objects
+/// \param hasFeature will be set to true if list contains Feature objects
+/// \param hasParameter will be set to true if list contains Parameter objects
+/// \param hasCompositeOwner will be set to true if list contains Sub-Feature objects
MODULEBASE_EXPORT void checkObjects(const QObjectPtrList& theObjects, bool& hasResult,
bool& hasFeature, bool& hasParameter, bool& hasCompositeOwner);
-/*! Sets the default coeffient into the driver calculated accordingly the shape type.
-It provides 1.e-4 for a shape withe Edge shape type
-\param theShape a shape to define the deviation coeffient,
-\param theDrawer a drawer
-*/
+/// Sets the default coeffient into the driver calculated accordingly the shape type.
+/// It provides 1.e-4 for results of construction type
+/// \param theResult a result object to define the deviation coeffient
+/// \param theDrawer a drawer
+MODULEBASE_EXPORT void setDefaultDeviationCoefficient(
+ const std::shared_ptr<ModelAPI_Result>& theResult,
+ const Handle(Prs3d_Drawer)& theDrawer);
+
+/// Sets the default coeffient into the driver calculated accordingly the shape type.
+/// It provides 1.e-4 for a shape withe Edge shape type
+/// \param theShape a shape to define the deviation coeffient,
+/// \param theDrawer a drawer
MODULEBASE_EXPORT void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
const Handle(Prs3d_Drawer)& theDrawer);
-/*! Obtains the color from the property manager and converts it to the OCCT color
-\param theSection a property section
-\param theName a property item name
-\param theDefault a default color value
-\return quantity color
-*/
+/// Obtains the color from the property manager and converts it to the OCCT color
+/// \param theSection a property section
+/// \param theName a property item name
+/// \param theDefault a default color value
+/// \return quantity color
MODULEBASE_EXPORT Quantity_Color color(const std::string& theSection,
const std::string& theName,
const std::string& theDefault);
-
/// Returns the object from the attribute
/// \param theObj an object
MODULEBASE_EXPORT ObjectPtr getObject(const AttributePtr& theAttribute);
MODULEBASE_EXPORT QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
int theMaxLineInPixels = 150);
-/*!
- Returns a container of referenced feature to the current object in the object document.
- \param theObject an object, which will be casted to a feature type
- \param theRefFeatures an output container
- */
+/// Returns a container of referenced feature to the current object in the object document.
+/// \param theObject an object, which will be casted to a feature type
+/// \param theRefFeatures an output container
void MODULEBASE_EXPORT refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
std::set<FeaturePtr>& theRefFeatures);
-/*!
- Returns true if the object if a sub child of the feature. The feature is casted to the
- composite one. If it is possible, the sub object check happens. The method is applyed
- recursively to the feature subs.
- \param theObject a candidate to be a sub object
- \param theFeature a candidate to be a composite feature
- \return a boolean value
- */
+/// Returns true if the object if a sub child of the feature. The feature is casted to the
+/// composite one. If it is possible, the sub object check happens. The method is applyed
+/// recursively to the feature subs.
+/// \param theObject a candidate to be a sub object
+/// \param theFeature a candidate to be a composite feature
+/// \return a boolean value
bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature);
-/*!
-* Returns true if the result is a sub object of some composite object
-* \param theObject a result object
-* \returns boolean value
-*/
+/// Returns true if the result is a sub object of some composite object
+/// \param theObject a result object
+/// \returns boolean value
bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject);
-/*!
-* Shows a dialog box about references. Ask whether they should be also removed.
-* \param theFeatures a list of features
-* \param theReferences a map of all references to the features
-* \param theParent a parent widget for the question message box
-* \param theReferencesToDelete an out set for references features to be removed
-* \return true if in message box answer is Yes
-*/
+/// Returns first result of the feature: the object itself if it is a result of
+/// first result of the object's feature
+/// \param theObject an object
+/// \return first result or NULL
+std::shared_ptr<ModelAPI_Result> MODULEBASE_EXPORT firstResult(const ObjectPtr& theObject);
+
+/// Returns true if the list contains at least one feature from the module document(PartSet)
+/// The Part features are skipped.
+/// \param theFeatures a list of features
+/// \bool true if it is found
+bool MODULEBASE_EXPORT hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures);
+
+/// Shows a dialog box about references. Ask whether they should be also removed.
+/// \param theFeatures a list of features
+/// \param theReferences a map of all references to the features
+/// \param theParent a parent widget for the question message box
+/// \param theReferencesToDelete an out set for references features to be removed
+/// \return true if in message box answer is Yes
bool MODULEBASE_EXPORT askToDelete(const std::set<FeaturePtr> aFeatures,
const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
QWidget* theParent,
std::set<FeaturePtr>& theReferencesToDelete);
-/*!
-* Converts a list of objects to set of corresponded features. If object is result, it is ingored
-* because the feauture only might be removed. But if result is in a parameter group, the feature
-* of this parameter is to be removed
-* \param theObjects a list of objects
-* \param theFeatures an out conteiner of features
-*/
+/// Converts a list of objects to set of corresponded features. If object is result, it is ingored
+/// because the feauture only might be removed. But if result is in a parameter group, the feature
+/// of this parameter is to be removed
+/// \param theObjects a list of objects
+/// \param theFeatures an out conteiner of features
void MODULEBASE_EXPORT convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures);
}
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
+#include <QMessageBox>
+
#include <string>
#include <set>
#include <sstream>
if (!aParameter.get())
return;
+ 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);
+ if (aRes != QMessageBox::Yes) {
+ setParameterName(aResultParameter, aMessage->oldName());
+ return;
+ }
+ }
+
// try to update the parameter feature according the new name
setParameterName(aResultParameter, aMessage->newName());
// TODO(spo): replace with ModelAPI_Session::get()->validators()->validate(aParameter, ParametersPlugin_Parameter::VARIABLE_ID())
#include <QTimer>
#include <QEvent>
#include <QKeyEvent>
+#include <QDialogButtonBox>
enum ColumnType {
Col_Name,
/////////////////////////////////////////////////////////////////////////////////////////////////
ParametersPlugin_WidgetParamsMgr::ParametersPlugin_WidgetParamsMgr(QWidget* theParent, const Config_WidgetAPI* theData)
- : ModuleBase_ModelWidget(theParent, theData)
+ : ModuleBase_ModelDialogWidget(theParent, theData)
{
QVBoxLayout* aLayout = new QVBoxLayout(this);
void ParametersPlugin_WidgetParamsMgr::updateParametersPart()
{
updateItem(myParameters, parametersItems(myParametersList));
- bool aIsValid = checkIsValid();
+ bool aIsValid = isValid();
enableButtons(aIsValid);
}
aText.replace(" ", "");
}
if (hasName(aText)) {
- myMessage = tr("Name %1 already exists.").arg(aText);
+ myMessage = tr("Name '%1' already exists.").arg(aText);
QTimer::singleShot(50, this, SLOT(sendWarning()));
return;
}
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
- if (aColumn == Col_Equation)
+ if (aColumn != Col_Comment)
updateParametersPart();
updateFeaturesPart();
+
+ onSelectionChanged();
}
void ParametersPlugin_WidgetParamsMgr::updateItem(QTreeWidgetItem* theItem,
void ParametersPlugin_WidgetParamsMgr::sendWarning()
{
QMessageBox::warning(this, tr("Warning"), myMessage);
+ QTreeWidgetItem* aItem = myTable->currentItem();
+ if (aItem)
+ myTable->editItem(aItem);
}
void ParametersPlugin_WidgetParamsMgr::onSelectionChanged()
{
- bool isValid = checkIsValid();
- if (isValid) {
- QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
+ QList<QTreeWidgetItem*> aItemsList = myTable->selectedItems();
+ bool aIsValid = isValid();
+ if (aIsValid) {
bool isParameter = false;
foreach(QTreeWidgetItem* aItem, aItemsList) {
if (aItem->parent() == myParameters) {
}
}
myInsertBtn->setEnabled(isParameter);
- myRemoveBtn->setEnabled(isParameter);
+ //myRemoveBtn->setEnabled(isParameter);
myUpBtn->setEnabled(isParameter);
myDownBtn->setEnabled(isParameter);
} else {
myInsertBtn->setEnabled(false);
- myRemoveBtn->setEnabled(false);
+ //myRemoveBtn->setEnabled(false);
myUpBtn->setEnabled(false);
myDownBtn->setEnabled(false);
}
+ myRemoveBtn->setEnabled(!aItemsList.isEmpty());
}
void ParametersPlugin_WidgetParamsMgr::enableButtons(bool theEnable)
myUpBtn->setEnabled(theEnable);
myDownBtn->setEnabled(theEnable);
}
+ myOkCancelBtn->button(QDialogButtonBox::Ok)->setEnabled(theEnable);
}
-bool ParametersPlugin_WidgetParamsMgr::checkIsValid()
+bool ParametersPlugin_WidgetParamsMgr::isValid()
{
QTreeWidgetItem* aItem;
bool aIsValid = true;
#ifndef ParametersPlugin_WidgetParamsMgr_H_
#define ParametersPlugin_WidgetParamsMgr_H_
-#include <ModuleBase_ModelWidget.h>
+#include <ModuleBase_ModelDialogWidget.h>
#include <QModelIndex>
#include <QAbstractItemDelegate>
#include <QTreeWidget>
* \ingroup GUI
* Represent a content of the property panel to show/modify parameters of some feature.
*/
-class ParametersPlugin_WidgetParamsMgr : public ModuleBase_ModelWidget
+class ParametersPlugin_WidgetParamsMgr : public ModuleBase_ModelDialogWidget
{
Q_OBJECT
public:
void updateParametersPart();
+ /// Returns true if values in the widget are valid
+ bool isValid();
+
/// Returns true if parameter with the given name already exists
bool hasName(const QString& theName) const;
/// Enable or disable buttons for parameters managemnt
void enableButtons(bool theEnable);
- bool checkIsValid();
-
QList<QStringList> featuresItems(const QList<FeaturePtr>& theFeatures, QList<FeaturePtr>& theFeatureList) const;
QList<QStringList> parametersItems(const QList<FeaturePtr>& theFeatures) const;
GeomShapePtr aShape = aResult->shape();
if(aShape.get()) {
switch(aShape->shapeType()) {
- case GeomAPI_Shape::COMPOUND: return aShape->isConnectedTopology() ?
- QIcon(":pictures/compoundofsolids.png") : QIcon(":pictures/compound.png");
+ case GeomAPI_Shape::COMPOUND: {
+ ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
+ if (aBody.get() && aBody->isConnectedTopology())
+ return QIcon(":pictures/compoundofsolids.png");
+ return QIcon(":pictures/compound.png");
+ }
case GeomAPI_Shape::COMPSOLID: return QIcon(":pictures/compsolid.png");
case GeomAPI_Shape::SOLID: return QIcon(":pictures/solid.png");
case GeomAPI_Shape::SHELL: return QIcon(":pictures/shell.png");
if (theActionId == "MOVE_CMD") {
FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
if (aFeature) {
+ ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
// part features can not be moved in the history.
- if (aFeature->getKind() == PartSetPlugin_Part::ID())
+ if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
aValid = false;
}
}
PartSet_SketcherMgr::sketchSelectionModes(theModes);
}
+void PartSet_Module::customSubShapesSelectionModes(QIntList& theTypes)
+{
+ if (theTypes.contains(TopAbs_FACE))
+ theTypes.append(SketcherPrs_Tools::Sel_Sketch_Face);
+ if (theTypes.contains(TopAbs_WIRE))
+ theTypes.append(SketcherPrs_Tools::Sel_Sketch_Wire);
+}
+
bool PartSet_Module::isMouseOverWindow()
{
return mySketchMgr->isMouseOverWindow();
void PartSet_Module::launchOperation(const QString& theCmdId)
{
storeConstraintsState(theCmdId.toStdString());
+ updateConstraintsState(theCmdId.toStdString());
+
ModuleBase_IModule::launchOperation(theCmdId);
}
mySketchMgr->showConstraintStates();
myHasConstraintShown = aShownStates;
}
+}
+
+void PartSet_Module::updateConstraintsState(const std::string& theFeatureKind)
+{
if (PartSet_SketcherMgr::constraintsIdList().contains(theFeatureKind.c_str())) {
// Show constraints if a constraint was anOperation
mySketchMgr->updateBySketchParameters(PartSet_Tools::Geometrical, true);
myHasConstraintShown[PartSet_Tools::Dimensional] = true;
myHasConstraintShown[PartSet_Tools::Expressions] = false;
}
-
-//******************************************************
-bool PartSet_Module::canActivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const
-{
- /*if (theMode == TopAbs_FACE) {
- Handle(PartSet_ResultSketchPrs) aSketchPrs = Handle(PartSet_ResultSketchPrs)::DownCast(theIO);
- if (!aSketchPrs.IsNull()) {
- ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
- if (anOperation) {
- ModuleBase_IPropertyPanel* aPropPanel = anOperation->propertyPanel();
- if (aPropPanel) {
- ModuleBase_ModelWidget* aModelWgt = aPropPanel->activeWidget();
- ModuleBase_WidgetSelector* aWgtSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aModelWgt);
- if (aWgtSelector) {
- return aWgtSelector->isFilterActivated();
- } else
- return true;
- } else
- return false;
- } else
- return false;
- }
- }*/
- return true;
-}
-
-//******************************************************
-bool PartSet_Module::needDeactivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const
-{
- if (theMode == TopAbs_FACE) {
- // Handle(PartSet_ResultSketchPrs) aSketchPrs = Handle(PartSet_ResultSketchPrs)::DownCast(theIO);
- // return !aSketchPrs.IsNull();
- }
- return false;
-}
/// \param theModes a list of modes
virtual void activeSelectionModes(QIntList& theModes);
+ /// Appends specific selection modes for the module to the list of types
+ /// \param theTypes a selection modes to be extended
+ virtual void customSubShapesSelectionModes(QIntList& theTypes);
+
/// Returns whether the mouse enter the viewer's window
/// \return true if items are added and there is no necessity to provide standard menu
bool isMouseOverWindow();
/// \return theAttribute
virtual AttributePtr findAttribute(const ObjectPtr& theObject, const GeomShapePtr& theGeomShape);
- /// Returns true if the given selection mode can be activated for the given presentgation
- /// \param theIO an object presentation
- /// \param theMode selection mode
- virtual bool canActivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const;
-
- /// Returns true if the given selection mode must be deactivated for the given presentgation in any case
- /// \param theIO an object presentation
- /// \param theMode selection mode
- virtual bool needDeactivateSelectionMode(const Handle(AIS_InteractiveObject)& theIO, int theMode) const;
-
public slots:
/// Redefines the parent method in order to customize the next case:
/// If the sketch nested operation is active and the presentation is not visualized in the viewer,
/// \param theFeatureKindId a feature kind
void storeConstraintsState(const std::string& theFeatureKindId);
+ /// If the feature kind is a geometrical or dimensional constraint, set visible state for
+ /// all types of constraints
+ /// \param theFeatureKindId a feature kind
+ void updateConstraintsState(const std::string& theFeatureKind);
+
/// Register validators for this module
virtual void registerValidators();
#include <gp_Pnt.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Compound.hxx>
//#define DEBUG_EMPTY_SHAPE
+//#define DEBUG_OPERATION_PRS
// multi-rotation/translation operation
//#define DEBUG_HIDE_COPY_ATTRIBUTE
PartSet_OperationPrs::PartSet_OperationPrs(ModuleBase_IWorkshop* theWorkshop)
: ViewerData_AISShape(TopoDS_Shape()), myWorkshop(theWorkshop), myUseAISWidth(false)
{
+#ifdef DEBUG_OPERATION_PRS
+ qDebug("PartSet_OperationPrs::PartSet_OperationPrs");
+#endif
myShapeColor = Quantity_Color(1, 1, 1, Quantity_TOC_RGB);
// first presentation for having correct Compute until presentation with shapes are set
const Handle(Prs3d_Presentation)& thePresentation,
const Standard_Integer theMode)
{
+#ifdef DEBUG_OPERATION_PRS
+ qDebug("PartSet_OperationPrs::Compute -- begin");
+#endif
+
SetColor(myShapeColor);
thePresentation->Clear();
bool aReadyToDisplay = !myShapeToPrsMap.IsEmpty();
XGUI_Displayer* aDisplayer = XGUI_Tools::workshop(myWorkshop)->displayer();
Handle(Prs3d_Drawer) aDrawer = Attributes();
// create presentations on the base of the shapes
+ BRep_Builder aBuilder;
+ TopoDS_Compound aComp;
+ aBuilder.MakeCompound(aComp);
for(NCollection_DataMap<TopoDS_Shape, Handle(AIS_InteractiveObject)>::Iterator anIter(myShapeToPrsMap);
anIter.More(); anIter.Next()) {
const TopoDS_Shape& aShape = anIter.Key();
+ aBuilder.Add(aComp, aShape);
// 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);
if (myUseAISWidth) {
}
StdPrs_WFDeflectionShape::Add(thePresentation, aShape, aDrawer);
}
-
+ Set(aComp);
if (!aReadyToDisplay) {
Events_InfoMessage("PartSet_OperationPrs",
"An empty AIS presentation: PartSet_OperationPrs").send();
new Events_Message(Events_Loop::eventByName(EVENT_EMPTY_OPERATION_PRESENTATION)));
Events_Loop::loop()->send(aMsg);
}
+#ifdef DEBUG_OPERATION_PRS
+ qDebug("PartSet_OperationPrs::Compute -- end");
+#endif
}
void PartSet_OperationPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
#include <SketchPlugin_SketchEntity.h>
+#include <SketcherPrs_Tools.h>
+
#include <Config_PropManager.h>
#include <BRep_Builder.hxx>
setAuxiliaryPresentationStyle(false);
// change deviation coefficient to provide more precise circle
- ModuleBase_Tools::setDefaultDeviationCoefficient(Shape(), Attributes());
+ ModuleBase_Tools::setDefaultDeviationCoefficient(myResult, Attributes());
AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
if (!myAuxiliaryCompound.IsNull()) {
#endif
void PartSet_ResultSketchPrs::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
- const Standard_Integer aMode)
+ const Standard_Integer theMode)
{
- if (aMode > 8)
+ int aMode = theMode;
+
+ if (aMode > 8 &&
+ aMode != SketcherPrs_Tools::Sel_Sketch_Face &&
+ aMode != SketcherPrs_Tools::Sel_Sketch_Wire)
// In order to avoid using custom selection modes
return;
bool aShapeIsChanged = false;
- if (aMode == AIS_Shape::SelectionMode(TopAbs_FACE) ||
- aMode == AIS_Shape::SelectionMode(TopAbs_WIRE)) {
+ if (aMode == SketcherPrs_Tools::Sel_Sketch_Face ||
+ aMode == SketcherPrs_Tools::Sel_Sketch_Wire) {
+ aMode = (aMode == SketcherPrs_Tools::Sel_Sketch_Face) ? AIS_Shape::SelectionMode(TopAbs_FACE)
+ : AIS_Shape::SelectionMode(TopAbs_WIRE);
#ifdef DEBUG_WIRE
const TopoDS_Shape& aShape = Shape();
debugInfo(aShape, TopAbs_VERTEX); // 24
/// Redefinition of virtual function
Standard_EXPORT virtual void ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
- const Standard_Integer aMode) ;
+ const Standard_Integer theMode) ;
private:
/// Appens sensitive and owners for wires of the given shape into selection
#include <ModuleBase_Operation.h>
#include <ModuleBase_WidgetEditor.h>
#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
#include <GeomDataAPI_Point2D.h>
if (!aContext.IsNull()) {
// MoveTo in order to highlight current object
aContext->MoveTo(theEvent->x(), theEvent->y(), theWnd->v3dView());
+ ModuleBase_Tools::selectionInfo(aContext, "PartSet_SketcherMgr::onMousePressed -- MoveTo");
}
// Remember highlighted objects for editing
ModuleBase_ISelection* aSelect = aWorkshop->selection();
// TODO
// SketchRectangle is a python feature, so its ID is passed just as a string
aIds << "SketchRectangle";
+ aIds.append(replicationsIdList());
aIds.append(constraintsIdList());
}
return aIds;
}
+const QStringList& PartSet_SketcherMgr::replicationsIdList()
+{
+ static QStringList aReplicationIds;
+ if (aReplicationIds.size() == 0) {
+ aReplicationIds << SketchPlugin_ConstraintMirror::ID().c_str();
+ aReplicationIds << SketchPlugin_MultiRotation::ID().c_str();
+ aReplicationIds << SketchPlugin_MultiTranslation::ID().c_str();
+ }
+ return aReplicationIds;
+}
+
const QStringList& PartSet_SketcherMgr::constraintsIdList()
{
- static QStringList aIds;
- if (aIds.size() == 0) {
- aIds << SketchPlugin_ConstraintLength::ID().c_str();
- aIds << SketchPlugin_ConstraintDistance::ID().c_str();
- aIds << SketchPlugin_ConstraintRigid::ID().c_str();
- aIds << SketchPlugin_ConstraintRadius::ID().c_str();
- aIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
- aIds << SketchPlugin_ConstraintParallel::ID().c_str();
- aIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
- aIds << SketchPlugin_ConstraintVertical::ID().c_str();
- aIds << SketchPlugin_ConstraintEqual::ID().c_str();
- aIds << SketchPlugin_ConstraintTangent::ID().c_str();
- aIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
- aIds << SketchPlugin_ConstraintMirror::ID().c_str();
- aIds << SketchPlugin_ConstraintAngle::ID().c_str();
- aIds << SketchPlugin_MultiRotation::ID().c_str();
- aIds << SketchPlugin_MultiTranslation::ID().c_str();
- aIds << SketchPlugin_ConstraintCollinear::ID().c_str();
- aIds << SketchPlugin_ConstraintMiddle::ID().c_str();
+ static QStringList aConstraintIds;
+ if (aConstraintIds.size() == 0) {
+ aConstraintIds << SketchPlugin_ConstraintLength::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintDistance::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintRigid::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintRadius::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintPerpendicular::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintParallel::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintHorizontal::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintVertical::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintEqual::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintTangent::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintCoincidence::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintAngle::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintCollinear::ID().c_str();
+ aConstraintIds << SketchPlugin_ConstraintMiddle::ID().c_str();
}
- return aIds;
+ return aConstraintIds;
}
void PartSet_SketcherMgr::sketchSelectionModes(QIntList& theModes)
/// Returns list of strings which contains id's of sketch operations
static const QStringList& sketchOperationIdList();
+ /// Returns list of strings which contains id's of sketch replication operations
+ static const QStringList& replicationsIdList();
+
/// Returns list of strings which contains id's of constraints operations
static const QStringList& constraintsIdList();
AttributeRefAttrPtr anAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
bool isObject = anAttr->isObject();
ObjectPtr anObject = anAttr->object();
- AttributePtr anAttributeAttr = anAttr->attr();
anAttrs = aFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
if (anAttrs.size() > 0) {
- std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttr = anAttrs.begin();
- for(; anAttr != anAttrs.end(); anAttr++) {
- if ((*anAttr).get() && (*anAttr)->id() != theAttribute->id()) {
+ std::list<std::shared_ptr<ModelAPI_Attribute> >::iterator anAttrIter = anAttrs.begin();
+ for(; anAttrIter != anAttrs.end(); anAttrIter++) {
+ if ((*anAttrIter).get() && (*anAttrIter)->id() != theAttribute->id()) {
std::shared_ptr<ModelAPI_AttributeRefAttr> aRef =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttr);
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
if (aRef->isObject() != isObject)
continue;
if (isObject) {
}
}
else { // the attribute reference
+ AttributePtr anAttributeAttr = anAttr->attr();
if (aRef->attr() == anAttributeAttr) {
theError = errorMessage(EqualAttributes,
anAttributeAttr.get() ? anAttributeAttr->id() : "",
# START DEBUG PURPOSES
# prepare a study without last operation to trap floating problem with degenerated line
-aPathToStore = os.path.join(os.getcwd(), "Data")
-print aPathToStore
-if not os.path.exists(aPathToStore):
- os.mkdir(aPathToStore)
-results = ModelAPI.StringList()
-ModelAPI.ModelAPI_Session.get().save(aPathToStore, results)
+#aPathToStore = os.path.join(os.getcwd(), "Data")
+#print aPathToStore
+#if not os.path.exists(aPathToStore):
+# os.mkdir(aPathToStore)
+#results = ModelAPI.StringList()
+#ModelAPI.ModelAPI_Session.get().save(aPathToStore, results)
# END DEBUG PURPOSES
b4 = body_4()
data()->addAttribute(EXTERNAL_ID(), ModelAPI_AttributeSelection::typeId());
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), EXTERNAL_ID());
- data()->addAttribute(INVERSED_ID(), ModelAPI_AttributeBoolean::typeId());
- AttributeBooleanPtr isInversed =
- std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(attribute(INVERSED_ID()));
- if (!isInversed->isInitialized())
- isInversed->setValue(false);
+ AttributeBooleanPtr isInversed = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
+ data()->addAttribute(INVERSED_ID(), ModelAPI_AttributeBoolean::typeId()));
// get the initial values
if (anEndAttr->isInitialized()) {
myYEndBefore = anEndAttr->y();
}
- data()->addAttribute(ARC_TYPE(), ModelAPI_AttributeString::typeId());
- std::dynamic_pointer_cast<ModelAPI_AttributeString>(
- data()->attribute(ARC_TYPE()))->setValue(ARC_TYPE_CENTER_START_END());
+ AttributeStringPtr anArcType = std::dynamic_pointer_cast<ModelAPI_AttributeString>(
+ data()->addAttribute(ARC_TYPE(), ModelAPI_AttributeString::typeId()));
data()->addAttribute(PASSED_POINT_ID(), GeomDataAPI_Point2D::typeId());
data()->addAttribute(TANGENT_POINT_ID(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(RADIUS_ID(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
+
+ // set after all to avoid in attributeChanged reference to not existing attributes
+ if (!isInversed->isInitialized())
+ isInversed->setValue(false);
+ anArcType->setValue(ARC_TYPE_CENTER_START_END());
}
void SketchPlugin_Arc::execute()
label="Points:"
tooltip="Select points for fillets"
type_choice="Vertices"
- greed ="true">
+ greed = "true"
+ clear_in_neutral_point="false">
<validator id="SketchPlugin_FilletVertexValidator"/>
</sketch_multi_selector>
<doublevalue label="Radius" tooltip="Fillet arc radius" id="ConstraintValue" accept_expressions="0" min="0" use_reset="false">
-/// \brief Set flags for angle constraint
-static void adjustAngle(ConstraintWrapperPtr theConstraint);
/// \brief Update mirror points
static void adjustMirror(ConstraintWrapperPtr theConstraint);
/// \brief Update a sign of the point-line distance constraint
std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
std::list<GCSConstraintPtr> aConstrList;
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
- *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
*(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
+ aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
+ *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
{
SketchSolver_ConstraintType aType = theConstraint->type();
// Update flags and parameters in constraints
- if (aType == CONSTRAINT_ANGLE)
- adjustAngle(theConstraint);
- else if (aType == CONSTRAINT_PT_LINE_DISTANCE)
+ if (aType == CONSTRAINT_PT_LINE_DISTANCE)
adjustPtLineDistance(theConstraint);
else if (aType == CONSTRAINT_SYMMETRIC)
adjustMirror(theConstraint);
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
{
std::shared_ptr<GCS::Line> aLine1 = std::dynamic_pointer_cast<GCS::Line>(theEntity1->entity());
+ bool isLine1Rev = theConstraint->boolean(
+ SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value();
+ GCS::Point aLine1Pt1 = isLine1Rev ? aLine1->p2 : aLine1->p1;
+ GCS::Point aLine1Pt2 = isLine1Rev ? aLine1->p1 : aLine1->p2;
+
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
+ bool isLine2Rev = theConstraint->boolean(
+ SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value();
+ GCS::Point aLine2Pt1 = isLine2Rev ? aLine2->p2 : aLine2->p1;
+ GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
+
GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
- *(aLine1), *(aLine2), theValue->parameter()));
+ aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->parameter()));
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
-void adjustAngle(ConstraintWrapperPtr theConstraint)
-{
- BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
-
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-
- bool isReversed[2] = {
- aConstraint->baseConstraint()->boolean(
- SketchPlugin_ConstraintAngle::ANGLE_REVERSED_FIRST_LINE_ID())->value(),
- aConstraint->baseConstraint()->boolean(
- SketchPlugin_ConstraintAngle::ANGLE_REVERSED_SECOND_LINE_ID())->value()
- };
-
- if (isReversed[0] != isReversed[1])
- aConstraint->setValue(aConstraint->value() - 180.0);
-}
-
void makeMirrorPoints(EntityWrapperPtr theOriginal,
EntityWrapperPtr theMirrored,
EntityWrapperPtr theMirrorLine)
PlaneGCSSolver_ParameterWrapper::~PlaneGCSSolver_ParameterWrapper()
{
- delete myValue;
+ if (!myProcessing)
+ delete myValue;
}
void PlaneGCSSolver_ParameterWrapper::setValue(double theValue)
void PlaneGCSSolver_Solver::clear()
{
- std::set<GCS::Constraint*>::const_iterator anIt = myConstraints.begin();
- for (; anIt != myConstraints.end(); ++anIt)
- myEquationSystem.removeConstraint(*anIt);
+ myEquationSystem.clear();
myConstraints.clear();
myParameters.clear();
}
return STATUS_INCONSISTENT;
Events_LongOp::start(this);
- GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
+ GCS::SolveStatus aResult = GCS::Success;
+ // if there is a constraint with all attributes constant, set fail status
+ GCS::SET_pD aParameters;
+ aParameters.insert(myParameters.begin(), myParameters.end());
+ std::set<GCS::Constraint*>::const_iterator aConstrIt = myConstraints.begin();
+ for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
+ GCS::VEC_pD aParams = (*aConstrIt)->params();
+ GCS::VEC_pD::const_iterator aPIt = aParams.begin();
+ for (; aPIt != aParams.end(); ++aPIt)
+ if (aParameters.find(*aPIt) != aParameters.end())
+ break;
+ if (aPIt == aParams.end()) {
+ aResult = GCS::Failed;
+ }
+ }
+ // solve equations
+ if (aResult == GCS::Success)
+ aResult = (GCS::SolveStatus)myEquationSystem.solve(myParameters);
+ if (aResult == GCS::Success) {
+ // additionally check redundant constraints
+ GCS::VEC_I aRedundantID;
+ myEquationSystem.getRedundant(aRedundantID);
+ if (!aRedundantID.empty())
+ aResult = GCS::Failed;
+ }
Events_LongOp::end(this);
SketchSolver_SolveStatus aStatus;
if (aResult == GCS::Success) {
myEquationSystem.applySolution();
aStatus = STATUS_OK;
- } else
+ } else {
+ undo();
aStatus = STATUS_FAILED;
+ }
return aStatus;
}
std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
bool isFullyRemoved = true;
+ // remove point-point coincidence
+ if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
+ isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved;
+ // remove sub-entities
const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
for (; aSIt != aSubs.end(); ++ aSIt)
bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
{
- if ((theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())) ||
- (theEntity->baseFeature() && isUsed(theEntity->baseFeature())))
- return false;
-
bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
- if (isFullyRemoved && theEntity->id() == myEntityLastID)
- --myEntityLastID;
+ if (isFullyRemoved) {
+ if (theEntity->type() == ENTITY_ARC) {
+ // remove arc additional constraints
+ std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::iterator
+ aFound = myArcConstraintMap.find(theEntity);
+ if (aFound != myArcConstraintMap.end()) {
+ myRemovedConstraints.insert(myRemovedConstraints.end(),
+ aFound->second.begin(), aFound->second.end());
+ myArcConstraintMap.erase(aFound);
+ }
+ }
+ if (theEntity->id() == myEntityLastID)
+ --myEntityLastID;
+ }
return isFullyRemoved;
}
if (anIt != myParameters.end()) {
myParameters.erase(anIt);
setNeedToResolve(true);
+ aParam->setProcessed(false);
}
else {
for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
if (anIt != myConst.end()) {
myConst.erase(anIt);
setNeedToResolve(true);
+ aParam->setProcessed(false);
}
}
}
- aParam->setProcessed(false);
return true;
}
void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
{
+ // no need to constraint a fixed arc
+ if (theArc->group() == GID_OUTOFGROUP)
+ return;
+
// Calculate additional parameters necessary for PlaneGCS
const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
if (!aSolver)
return;
+ aSolver->clear();
if (myExistArc)
processArcs();
#include <SketchSolver_ConstraintMiddle.h>
+#include <SketchSolver_Builder.h>
+#include <SketchSolver_Manager.h>
+
+#include <GeomAPI_XY.h>
+
SketchSolver_ConstraintMiddle::SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint)
: SketchSolver_Constraint(theConstraint)
{
}
}
+ // Mirrored entities are placed out-of-group by default, due to they are copies.
+ // Place them into current group manually.
+ std::vector<EntityWrapperPtr>::iterator aMirIt = theMirrorEntities.begin();
+ for (; aMirIt != theMirrorEntities.end(); ++aMirIt)
+ (*aMirIt)->setGroup(myGroupID);
+
if (theBaseEntities.size() > theMirrorEntities.size())
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
}
aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
}
- myStorage->addConstraint(myBaseConstraint, aMirConstrList);
// update mirrored features to be in the current group
for (aMIt = aMirrorList.begin(); aMIt != aMirrorList.end(); ++aMIt)
myStorage->update((*aMIt)->baseFeature(), myGroupID);
+ myStorage->addConstraint(myBaseConstraint, aMirConstrList);
}
void SketchSolver_ConstraintMirror::update()
{
cleanErrorMsg();
- AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
- if (aMirroredRefList->size() != myNumberOfObjects) {
- remove();
- process();
- return;
- }
- adjustConstraint();
+ remove();
+ process();
}
void SketchSolver_ConstraintMirror::adjustConstraint()
{
bool aResolved = false;
bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
- if (myStorage->isNeedToResolve() && !isGroupEmpty) {
+ if (myStorage->isNeedToResolve() &&
+ (!isGroupEmpty || !myConflictingConstraints.empty() || myPrevResult == STATUS_FAILED)) {
if (!mySketchSolver)
mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
try {
if (myStorage->hasDuplicatedConstraint())
aResult = STATUS_INCONSISTENT;
- else {
+ else if (!isGroupEmpty) {
// To avoid overconstraint situation, we will remove temporary constraints one-by-one
// and try to find the case without overconstraint
bool isLastChance = false;
updateMultiConstraints(myConstraints);
if (myPrevResult != STATUS_OK || myPrevResult == STATUS_UNKNOWN) {
getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
- // the error message should be changed before sending the message
- sendMessage(EVENT_SOLVER_REPAIRED, myConflictingConstraints);
+ std::set<ObjectPtr> aConflicting = myConflictingConstraints;
myConflictingConstraints.clear();
myPrevResult = STATUS_OK;
+ // the error message should be changed before sending the message
+ sendMessage(EVENT_SOLVER_REPAIRED, aConflicting);
}
} else {
mySketchSolver->undo();
}
if (!(*aGroupIter)->isConsistent()) { // some constraints were removed, try to split the group
(*aGroupIter)->splitGroup(aSeparatedGroups);
- //if (!(*aGroupIter)->getWorkplane()->string(
- // SketchPlugin_Sketch::SOLVER_ERROR())->value().empty())
+ if (!(*aGroupIter)->getWorkplane()->string(
+ SketchPlugin_Sketch::SOLVER_ERROR())->value().empty() ||
+ (*aGroupIter)->isFailed())
aGroupsToResolve.push_back(*aGroupIter);
}
aGroupIter++;
std::list<SketchSolver_Group*>::const_iterator aGroupIt = myGroups.begin();
for (; aGroupIt != myGroups.end(); ++aGroupIt) {
CompositeFeaturePtr aSketch = (*aGroupIt)->getWorkplane();
- if (!aSketch->data()->isValid()) {
+ bool isSketchValid = aSketch->data() && aSketch->data()->isValid();
+
+ if (isSketchValid) {
+ std::shared_ptr<GeomDataAPI_Dir> aNormal =
+ std::dynamic_pointer_cast<GeomDataAPI_Dir>(aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
+ isSketchValid = aNormal && aNormal->isInitialized();
+ }
+
+ if (!isSketchValid) {
myDoF.erase(aSketch);
continue;
}
#include <SketchPlugin_Line.h>
#include <SketchPlugin_Point.h>
#include <SketchPlugin_IntersectionPoint.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintRigid.h>
}
+bool SketchSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
+{
+ std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
+ std::list<EntityWrapperPtr>::const_iterator aPIt;
+
+ CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
+ for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
+ for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+ if (aPtPtIt->first == *aPIt ||
+ aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
+ break;
+ if (aPIt != aPoints.end())
+ break;
+ }
+
+ if (aPtPtIt == myCoincidentPoints.end())
+ return true; // already removed
+
+ // Create new copies of coincident points
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+ std::list<EntityWrapperPtr> aNewPoints;
+ for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+ aNewPoints.push_back(aBuilder->createAttribute(
+ (*aPIt)->baseAttribute(), myGroupID, mySketchID));
+
+ // Find all points fallen out of group of coincident points
+ std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
+ aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
+ std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
+ for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
+ aNotCoinc[*aTempIt] = EntityWrapperPtr();
+ std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
+ aConstrIt = myConstraintMap.begin();
+ for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
+ if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ AttributePtr anAttrA, anAttrB;
+ if (aConstrIt->first->data()->isValid()) {
+ if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
+ continue;
+ anAttrA = aRefAttrA->attr();
+ anAttrB = aRefAttrB->attr();
+ } else {
+ // obtain attributes from the constraint wrapper
+ ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
+ anAttrA = aWrapper->entities().front()->baseAttribute();
+ anAttrB = aWrapper->entities().back()->baseAttribute();
+ }
+ std::map<AttributePtr, EntityWrapperPtr>::iterator
+ aFound = myAttributeMap.find(anAttrA);
+ if (aFound != myAttributeMap.end())
+ aNotCoinc.erase(aFound->second);
+ aFound = myAttributeMap.find(anAttrB);
+ if (aFound != myAttributeMap.end())
+ aNotCoinc.erase(aFound->second);
+ }
+ if (aNotCoinc.empty())
+ return false;
+ std::list<EntityWrapperPtr>::const_iterator aNewPIt;
+ for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
+ aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
+ if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
+ aNotCoinc[*aPIt] = *aNewPIt;
+ }
+
+ // Find all features and constraints uses coincident points
+ std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
+ std::set<EntityWrapperPtr> anUpdFeatures;
+ std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
+ for (; aFIt != myFeatureMap.end(); ++aFIt) {
+ if (!aFIt->second)
+ continue; // avoid not completed arcs
+ for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+ if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
+ continue;
+ std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
+ std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
+ bool isUpd = false;
+ for (; aSIt != aSubs.end(); ++aSIt)
+ if (*aSIt == aNotCIt->first) {
+ *aSIt = aNotCIt->second;
+ isUpd = true;
+ }
+ if (isUpd) {
+ aFIt->second->setSubEntities(aSubs);
+ anUpdFeatures.insert(aFIt->second);
+ }
+ }
+ }
+ // update features
+ std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
+ for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
+ update(EntityWrapperPtr(*anUpdIt));
+
+ // remove not coincident points
+ for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+ if (aPtPtIt->second.size() <= 1) {
+ myCoincidentPoints.erase(aPtPtIt);
+ break;
+ }
+ if (aPtPtIt->first == aNotCIt->first) {
+ std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
+ EntityWrapperPtr aNewMaster = *aSlaves.begin();
+ aSlaves.erase(aSlaves.begin());
+ myCoincidentPoints.erase(aPtPtIt);
+ myCoincidentPoints[aNewMaster] = aSlaves;
+ aPtPtIt = myCoincidentPoints.find(aNewMaster);
+ } else
+ aPtPtIt->second.erase(aNotCIt->first);
+ }
+ return true;
+}
+
bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
{
bool isFullyRemoved = true;
FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
if (aBaseFeature)
isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
- else
- isFullyRemoved = SketchSolver_Storage::removeEntity((*anEntIt)->baseAttribute()) && isFullyRemoved;
+ else {
+ AttributePtr aBaseAttr = (*anEntIt)->baseAttribute();
+ if (aBaseAttr)
+ isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseAttr) && isFullyRemoved;
+ else
+ remove(*anEntIt);
+ }
}
std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
public:
SketchSolver_Storage(const GroupID& theGroup)
: myGroupID(theGroup),
+ mySketchID(EID_UNKNOWN),
myNeedToResolve(false),
myEventsBlocked(false),
myExistArc(false)
/// \return \c true if the parameter has been removed
virtual bool remove(ParameterWrapperPtr theParameter) = 0;
+ /// \brief Remove point-point coincidence
+ SKETCHSOLVER_EXPORT bool removeCoincidence(ConstraintWrapperPtr theConstraint);
+
/// \brief Update the group for the given entity, its sub-entities and parameters
virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup) = 0;
/// \brief Update the group for the given parameter
EntityWrapperPtr getNormal() const;
protected:
+ EntityID mySketchID; ///< identifier of the sketch
GroupID myGroupID; ///< identifier of the group, this storage belongs to
bool myNeedToResolve; ///< parameters are changed and group needs to be resolved
bool myEventsBlocked; ///< indicates that features do not send events
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_AttributeRefAttr.h>
#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintMiddle.h>
/** \brief Search the entity/parameter with specified ID in the list of elements
* \param[in] theEntityID unique ID of the element
std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
for (; anIt != anEntities.end(); ++anIt) {
isUpdated = update(*anIt) || isUpdated;
- // do not update constrained entities for Multi constraints
- if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION)
+ // do not update constrained entities for Multi constraints,
+ // and for middle point constraint translated to equal lines
+ ConstraintPtr aBaseConstraint = theConstraint->baseConstraint();
+ if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type == SLVS_C_MULTI_TRANSLATION ||
+ (aBaseConstraint && aBaseConstraint->getKind() == SketchPlugin_ConstraintMiddle::ID() &&
+ aSlvsConstr.type != SLVS_C_AT_MIDPOINT))
continue;
Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id();
void SolveSpaceSolver_Storage::storeWorkplane(EntityWrapperPtr theSketch)
{
- myWorkplaneID = (Slvs_hEntity)theSketch->id();
+ mySketchID = theSketch->id();
+ myWorkplaneID = (Slvs_hEntity)mySketchID;
// Update sub-entities of the sketch
std::list<EntityWrapperPtr> aSubEntities = theSketch->subEntities();
for (; aSIt != aSubs.end(); ++aSIt)
changeGroup(*aSIt, theGroup);
- if (theEntity->group() != theGroup) {
- theEntity->setGroup(theGroup);
- int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities);
- if (aPos >= 0 && aPos < (int)myEntities.size()) {
- myEntities[aPos].group = (Slvs_hGroup)theGroup;
+ theEntity->setGroup(theGroup);
+ int aPos = Search((Slvs_hEntity)theEntity->id(), myEntities);
+ if (aPos >= 0 && aPos < (int)myEntities.size()) {
+ if (myEntities[aPos].group != (Slvs_hGroup)theGroup)
setNeedToResolve(true);
- }
+ myEntities[aPos].group = (Slvs_hGroup)theGroup;
}
}
}
-bool SolveSpaceSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
-{
- std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aPIt;
-
- CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
- for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
- for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
- if (aPtPtIt->first == *aPIt ||
- aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
- break;
- if (aPIt != aPoints.end())
- break;
- }
-
- if (aPtPtIt == myCoincidentPoints.end())
- return true; // already removed
-
- // Create new copies of coincident points
- BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
- std::list<EntityWrapperPtr> aNewPoints;
- for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
- aNewPoints.push_back(aBuilder->createAttribute(
- (*aPIt)->baseAttribute(), myGroupID, myWorkplaneID));
-
- // Find all points fallen out of group of coincident points
- std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
- aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
- std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
- for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
- aNotCoinc[*aTempIt] = EntityWrapperPtr();
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
- aConstrIt = myConstraintMap.begin();
- for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
- if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
- AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
- AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
- AttributePtr anAttrA, anAttrB;
- if (aConstrIt->first->data()->isValid()) {
- if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
- continue;
- anAttrA = aRefAttrA->attr();
- anAttrB = aRefAttrB->attr();
- } else {
- // obtain attributes from the constraint wrapper
- ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
- anAttrA = aWrapper->entities().front()->baseAttribute();
- anAttrB = aWrapper->entities().back()->baseAttribute();
- }
- std::map<AttributePtr, EntityWrapperPtr>::iterator
- aFound = myAttributeMap.find(anAttrA);
- if (aFound != myAttributeMap.end())
- aNotCoinc.erase(aFound->second);
- aFound = myAttributeMap.find(anAttrB);
- if (aFound != myAttributeMap.end())
- aNotCoinc.erase(aFound->second);
- }
- if (aNotCoinc.empty())
- return false;
- std::list<EntityWrapperPtr>::const_iterator aNewPIt;
- for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
- aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
- if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
- aNotCoinc[*aPIt] = *aNewPIt;
- }
-
- // Find all features and constraints uses coincident points
- std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
- std::set<EntityWrapperPtr> anUpdFeatures;
- std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt) {
- if (!aFIt->second)
- continue; // avoid not completed arcs
- for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
- if (!aNotCIt->second || !aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
- continue;
- std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
- std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
- bool isUpd = false;
- for (; aSIt != aSubs.end(); ++aSIt)
- if (*aSIt == aNotCIt->first) {
- *aSIt = aNotCIt->second;
- isUpd = true;
- }
- if (isUpd) {
- aFIt->second->setSubEntities(aSubs);
- anUpdFeatures.insert(aFIt->second);
- }
- }
- }
- // update features
- std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
- for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
- update(EntityWrapperPtr(*anUpdIt));
-
- // remove not coincident points
- for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
- if (aPtPtIt->second.size() <= 1) {
- myCoincidentPoints.erase(aPtPtIt);
- break;
- }
- if (aPtPtIt->first == aNotCIt->first) {
- std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
- EntityWrapperPtr aNewMaster = *aSlaves.begin();
- aSlaves.erase(aSlaves.begin());
- myCoincidentPoints.erase(aPtPtIt);
- myCoincidentPoints[aNewMaster] = aSlaves;
- aPtPtIt = myCoincidentPoints.find(aNewMaster);
- } else
- aPtPtIt->second.erase(aNotCIt->first);
- }
- return true;
-}
-
bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
{
std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
/// \return \c true if the parameter has been removed
virtual bool remove(ParameterWrapperPtr theParameter);
- /// \brief Remove point-point coincidence
- bool removeCoincidence(ConstraintWrapperPtr theConstraint);
-
/// \brief Update the group for the given entity, its sub-entities and parameters
virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup);
/// \brief Update the group for the given parameter
/// Selection mode for line of dimension
Sel_Dimension_Line,
- /// Selection mode foe text of dimension
- Sel_Dimension_Text
+ /// Selection mode for text of dimension
+ Sel_Dimension_Text,
+
+ /// Selectiom mode for faces selection on sketch
+ Sel_Sketch_Face,
+
+ /// Selectiom mode for wires selection on sketch
+ Sel_Sketch_Wire
};
/// Type of angle
/// \return a list of group names
QStringList actionObjectGroups(const QString& theName);
+ /// Updates menu for object browser
+ void updateObjectBrowserMenu();
+
/// Updates menu for viewer
void updateViewerMenu();
void addFeatures(QMenu* theMenu) const;
- /// Updates menu for object browser
- void updateObjectBrowserMenu();
-
/// Creates menu for object browser
void buildObjBrowserMenu();
// An object
if (aObj->isDisabled())
return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag;
+
+ if (aSession->moduleDocument() != aObj->document())
+ if (aActiveDoc != aObj->document())
+ return theIndex.column() == 1? Qt::ItemIsSelectable : aNullFlag;
bool isCompositeSub = false;
// An object which is sub-object of a composite object can not be accessible in column 1
bool isShading = false;
if (aPrs.get() != NULL) {
anAIS = aPrs->getAISObject(anAIS);
+ if (anAIS.get()) {
+ // correct deviation coefficient for
+ Handle(AIS_InteractiveObject) anAISPrs = anAIS->impl<Handle(AIS_InteractiveObject)>();
+ if (!anAISPrs.IsNull()) {
+ Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(anAISPrs);
+ if (!aShapePrs.IsNull()) {
+ TopoDS_Shape aShape = aShapePrs->Shape();
+ if (!aShape.IsNull())
+ ModuleBase_Tools::setDefaultDeviationCoefficient(aShape, anAISPrs->Attributes());
+ }
+ }
+ }
} else {
ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
if (aResult.get() != NULL) {
if (!anAIS.IsNull()) {
emit beforeObjectErase(theObject, anObject);
aContext->Remove(anAIS, false/*update viewer*/);
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::erase -- Remove");
aErased = true;
}
}
aContext->Deactivate(aAISIO, 0);
#endif
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::redisplay -- Redisplay");
+
if (aNeedToRestoreSelection)
myWorkshop->module()->restoreSelection();
deactivateAIS(anAIS);
// the selection from the previous activation modes should be cleared manually (#26172)
aContext->LocalContext()->ClearOutdatedSelection(anAIS, true);
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::deactivate -- ClearOutdatedSelection");
if (theUpdateViewer)
updateViewer();
}
}
if (!aShapesToBeSelected.IsEmpty())
XGUI_Displayer::AddOrRemoveSelectedShapes(aContext, aShapesToBeSelected);
- } else {
+ } else { // it seems the next code is obsolete as the context is always opened in SHAPER
aContext->UnhilightCurrents(false);
aContext->ClearCurrents(false);
foreach (ModuleBase_ViewerPrsPtr aPrs, theValues) {
}
}
}
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::setSelected -- AddOrRemoveSelected/UnhilightCurrents(no local context)");
if (theUpdateViewer)
updateViewer();
}
if (theUpdateViewer)
updateViewer();
}
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::eraseAll -- Remove");
myResult2AISObjectMap.clear();
#ifdef DEBUG_DISPLAY
qDebug("eraseAll");
{
if (!theObject.IsNull()) {
theContext->Deactivate(theObject);
+ ModuleBase_Tools::selectionInfo(theContext, "XGUI_Displayer::deactivateObject -- Deactivate");
//if (theClear) {
//theObject->ClearSelected();
// theContext->LocalContext()->ClearOutdatedSelection(theObject, true);
if (!aContext.IsNull()) {
if (myWorkshop->module()) {
int aMode = (theMode > 8)? theMode : AIS_Shape::SelectionType(theMode);
- if (myWorkshop->module()->canActivateSelectionMode(theIO, aMode))
- aContext->Activate(theIO, theMode, false);
+ aContext->Activate(theIO, theMode, false);
} else
aContext->Activate(theIO, theMode, false);
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::activateAIS -- Activate");
+
#ifdef DEBUG_ACTIVATE_AIS
ObjectPtr anObject = getObject(theIO);
anInfo.append(ModuleBase_Tools::objectInfo((*anIt)));
aContext->Deactivate(theIO);
else
aContext->Deactivate(theIO, theMode);
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::deactivateAIS -- Deactivate");
#ifdef DEBUG_DEACTIVATE_AIS
ObjectPtr anObject = getObject(theIO);
Handle(AIS_InteractiveObject) anAISIO = theAIS->impl<Handle(AIS_InteractiveObject)>();
if (!anAISIO.IsNull() && aContext->IsDisplayed(anAISIO)) {
aContext->Remove(anAISIO, false/*update viewer*/);
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::eraseAIS -- Remove");
aErased = true;
}
}
for (; itr.More(); itr.Next() ) {
Standard_Integer aMode = itr.Value();
int aShapeMode = (aMode > 8)? aMode : AIS_Shape::SelectionType(aMode);
- if (!theModes.contains(aMode) || (myWorkshop->module()->needDeactivateSelectionMode(theIO, aShapeMode))) {
+ if (!theModes.contains(aMode)) {
deactivateAIS(theIO, aMode);
isDeactivated = true;
}
// the selection from the previous activation modes should be cleared manually (#26172)
theIO->ClearSelected();
aContext->LocalContext()->ClearOutdatedSelection(theIO, true);
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_Displayer::activate -- ClearSelected/ClearOutdatedSelection");
// For performance issues
//if (theUpdateViewer)
// updateViewer();
void XGUI_ModuleConnector::activateSubShapesSelection(const QIntList& theTypes)
{
+ QIntList aTypes = theTypes;
+
XGUI_Displayer* aDisp = myWorkshop->displayer();
- aDisp->activateObjects(theTypes, activeObjects(aDisp->displayedObjects()));
+ myWorkshop->module()->customSubShapesSelectionModes(aTypes);
+ aDisp->activateObjects(aTypes, activeObjects(aDisp->displayedObjects()));
}
void XGUI_ModuleConnector::deactivateSubShapesSelection()
{
QObjectPtrList aSelectedData = selectedObjects();
if (aSelectedData.size() > 0) {
- ObjectPtr aFeature = aSelectedData.first();
- if (aFeature) { // Selection happens in TreeView
- QObjectPtrList aList;
- aList.append(aFeature);
- // check whether the object can be deleted. There should not be parts which are not loaded
- if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aList))
+ ObjectPtr anObject = aSelectedData.first();
+ if (anObject.get()) { // Selection happens in TreeView
+ // check whether the object can be renamed. There should not be parts which are not loaded
+ std::set<FeaturePtr> aFeatures;
+ aFeatures.insert(ModelAPI_Feature::feature(anObject));
+ if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aFeatures))
return;
// Find index which corresponds the feature
QModelIndex aIndex;
foreach(QModelIndex aIdx, selectedIndexes()) {
ObjectPtr aFea = dataModel()->object(aIdx);
- if (dataModel()->object(aIdx)->isSame(aFeature)) {
+ if (dataModel()->object(aIdx)->isSame(anObject)) {
aIndex = aIdx;
break;
}
#include "XGUI_ErrorMgr.h"
#include "XGUI_Tools.h"
#include "XGUI_ObjectsBrowser.h"
+#include "XGUI_ContextMenuMgr.h"
#include <ModuleBase_IPropertyPanel.h>
#include <ModuleBase_ModelWidget.h>
/// processing delete by workshop
XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
- // property panel child object is processed to process delete performed on Apply button of PP
- if (theObject == aBrowser->treeView() ||
- isChildObject(theObject, aViewPort) ||
- isPPChildObject)
- XGUI_Tools::workshop(myWorkshop)->deleteObjects();
- isAccepted = true;
+ bool isToDeleteObject = false;
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
+ if (theObject == aBrowser->treeView()) {
+ aContextMenuMgr->updateObjectBrowserMenu();
+ isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
+ }
+ else if (isChildObject(theObject, aViewPort)) {
+ aContextMenuMgr->updateViewerMenu();
+ isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
+ }
+ else if (isPPChildObject) {
+ // property panel child object is processed to process delete performed on Apply button of PP
+ isToDeleteObject = true;
+ }
+ if (isToDeleteObject) {
+ aWorkshop->deleteObjects();
+ isAccepted = true;
+ }
}
return isAccepted;
std::string aPreviosAttributeID;
if(myActiveWidget) {
aPreviosAttributeID = myActiveWidget->attributeID();
+ myActiveWidget->processValueState();
myActiveWidget->deactivate();
myActiveWidget->setHighlighted(false);
}
#include <ModelAPI_ResultCompSolid.h>
#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_Tools.h>
#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
aContext->AddOrRemoveSelected(anOwner, isUpdateViewer);
}
}
+ ModuleBase_Tools::selectionInfo(aContext, "XGUI_SelectionMgr::setSelectedOwners -- AddOrRemoveSelected");
}
//**************************************************************
#include "XGUI_Workshop.h"
#include "ModuleBase_IWorkshop.h"
+#include "ModuleBase_Tools.h"
#include <TopoDS_Shape.hxx>
#include <ModelAPI_Object.h>
#include <iostream>
#include <sstream>
+#include <string>
namespace XGUI_Tools {
//******************************************************************
}
}*/
+
//******************************************************************
-bool canRemoveOrRename(QWidget* theParent, const QObjectPtrList& theObjects)
+bool canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& theFeatures)
{
bool aResult = true;
- QString aNotActivatedNames;
- if (!XGUI_Tools::allDocumentsActivated(aNotActivatedNames)) {
- DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
- bool aFoundPartSetObject = false;
- foreach (ObjectPtr aObj, theObjects) {
- if (aObj->groupName() == ModelAPI_ResultPart::group())
- continue;
- aFoundPartSetObject = aObj->document() == aModuleDoc;
- }
+ std::string aNotActivatedNames;
+ if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
+ bool aFoundPartSetObject = ModuleBase_Tools::hasModuleDocumentFeature(theFeatures);
if (aFoundPartSetObject) {
QMessageBox::StandardButton aRes = QMessageBox::warning(theParent, 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),
+%1. Whould you like to continue?").arg(aNotActivatedNames.c_str()),
QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
aResult = aRes == QMessageBox::Yes;
}
return true;
}
-//******************************************************************
-bool allDocumentsActivated(QString& theNotActivatedNames)
-{
- bool anAllPartActivated = true;
- QStringList aRefNames;
-
- DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
- int aSize = aRootDoc->size(ModelAPI_ResultPart::group());
- for (int i = 0; i < aSize; i++) {
- ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), i);
- ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(aObject);
- if (!aPart->isActivated()) {
- anAllPartActivated = false;
- aRefNames.append(aObject->data()->name().c_str());
- }
- }
- theNotActivatedNames = aRefNames.join(", ");
- return anAllPartActivated;
-}
-
//**************************************************************
XGUI_Workshop* workshop(ModuleBase_IWorkshop* theWorkshop)
all objects in the list are not PartSet document.
It shows the warning control if the result is false.
\param theParent a parent for the warning control
- \param aList a list of object
+ \param theFeatures a list of checked features
\return a boolean value
*/
-bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const QObjectPtrList& aList);
+bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& theFeatures);
/*!
Check possibility to rename object
*/
bool canRename(const ObjectPtr& theObject, const QString& theName);
-/*!
- Returns true if there are no parts in the document, which are not activated
- \param theNotActivatedNames out string which contains not activated names
- \return a boolean value
- */
-bool XGUI_EXPORT allDocumentsActivated(QString& theNotActivatedNames);
-
/*!
Returns converted workshop
\param theWorkshop an interface workshop
//Config_PropManager::registerProp("Visualization", "object_default_color", "Object color",
// Config_Prop::Color, "225,225,225");
- Config_PropManager::registerProp("Visualization", "result_body_color", "Body color",
+ Config_PropManager::registerProp("Visualization", "result_body_color", "Result color",
Config_Prop::Color, ModelAPI_ResultBody::DEFAULT_COLOR());
Config_PropManager::registerProp("Visualization", "result_group_color", "Group color",
Config_Prop::Color, ModelAPI_ResultGroup::DEFAULT_COLOR());
QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
if (!abortAllOperations())
return;
- // check whether the object can be deleted. There should not be parts which are not loaded
- if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
- return;
bool hasResult = false;
bool hasFeature = false;
// moving and negative consequences connected with processing of already moved items
mySelector->clearSelection();
// check whether the object can be moved. There should not be parts which are not loaded
- if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
+ std::set<FeaturePtr> aFeatures;
+ ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
+ if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
return;
DocumentPtr anActiveDocument = aMgr->activeDocument();
FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
- foreach (ObjectPtr aObject, anObjects) {
- if (!myModule->canApplyAction(aObject, anActionId))
+ std::set<FeaturePtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
+ for (; anIt != aLast; anIt++) {
+ FeaturePtr aFeature = *anIt;
+ if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
continue;
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
- if (aFeature.get()) {
- anActiveDocument->moveFeature(aFeature, aCurrentFeature);
- aCurrentFeature = anActiveDocument->currentFeature(true);
- }
+ anActiveDocument->moveFeature(aFeature, aCurrentFeature);
+ aCurrentFeature = anActiveDocument->currentFeature(true);
}
aMgr->finishOperation();
}