* Add checkboxes to allow dealing with conflicting constraints and notify about changes with constraints.
* Add class to resolve conflicting constrains.
* Algorithm to check arcs in sketch on tangential conflict.
* Move algorithm of vertical/horizontal auto constraint conflict in SketchPlugin_OverConstraintsResolver.
- **Size** defines size of coordinate planes;
- **Thickness** defines thickness of coordinate plane borders;
-- **Rotate to plane when selected** check-box turns on/off automatic switch the viewer to the top view for the selected sketch plane.
+- **Rotate to plane when selected** check-box turns on/off automatic switch the viewer to the top view for the selected sketch plane;
- **Angular tolerance** defines defines an angular tolerance for automatic creation of horizontal and vertical constraints;
- **Default spline weight** defines default weight for B-spline nodes during creation. The default value can be changed by editing of the spline;
-- **Cursor for sketch operation** defines a cursor which indicates a launched sketcher sub-operation.
+- **Cursor for sketch operation** defines a cursor which indicates a launched sketcher sub-operation;
- **Create sketch entities by dragging** defines a style of sketch etities creation. It concerns creation of lines, rectangles, circles, arcs, ellipses, elliptic arcs. If it is switched ON then points of objects have to be defined by mouse press - mouse move - mouse release. Otherwise every point of an object has to be defined by mouse click;
+- **Allow automatic constraint substitution/remove** allows automatic resolving of conflicting constraints.
+ The following conflicts could be processed:
+ - Horizontal/Vertical automatic constraints (this last constraint will be removed);
+ - Pair of arcs connected smoothly, which centers are coincident (Tangency between arcs will be removed);
+- **Notify automatic constraint substitution/remove** defines a message box to be shown to the user, if the conflicting constraints situation is automatically resolved.
.. _viewer_preferences:
return myShapes;
}
+/// Creates an empty message
+ModelAPI_CheckConstraintsMessage::ModelAPI_CheckConstraintsMessage(const Events_ID theID, const void* theSender)
+ :Events_Message(theID, theSender)
+{
+}
+
+ModelAPI_CheckConstraintsMessage::~ModelAPI_CheckConstraintsMessage()
+{
+}
+
+const std::set<ObjectPtr>& ModelAPI_CheckConstraintsMessage::constraints() const
+{
+ return myConstraints;
+}
+
+void ModelAPI_CheckConstraintsMessage::setConstraints(const std::set<ObjectPtr>& theConstraints)
+{
+ myConstraints = theConstraints;
+}
+
// ===== ModelAPI_FeaturesLicenseValidMessage =====
ModelAPI_FeaturesLicenseValidMessage::ModelAPI_FeaturesLicenseValidMessage(
/// Event ID that 1D-fillet failed (comes with ModelAPI_ShapesFailedMessage)
MAYBE_UNUSED static const char * EVENT_OPERATION_SHAPES_FAILED = "OperationShapesFailed";
+MAYBE_UNUSED static const char * EVENT_CHECK_CONSTRAINTS = "CheckConstrains";
+
+MAYBE_UNUSED static const char * EVENT_REMOVE_CONSTRAINTS = "RemoveConstrains";
+
/// Event ID that license of specified features is checked and valid
MAYBE_UNUSED static const char * EVENT_FEATURE_LICENSE_VALID = "FeaturesLicenseValid";
std::list< std::shared_ptr<GeomAPI_Shape> > myShapes;
};
+///Message that sends the constraints to check or remove
+class ModelAPI_CheckConstraintsMessage : public Events_Message
+{
+public:
+ /// Creates an empty message
+ MODELAPI_EXPORT ModelAPI_CheckConstraintsMessage(const Events_ID theID, const void* theSender = 0);
+ /// The virtual destructor
+ MODELAPI_EXPORT virtual ~ModelAPI_CheckConstraintsMessage();
+
+ ///Get list of constrains
+ MODELAPI_EXPORT const std::set<ObjectPtr>& constraints() const;
+
+ ///Set list of constrains
+ MODELAPI_EXPORT void setConstraints(const std::set<ObjectPtr>& theConstraints);
+
+private:
+ std::set<ObjectPtr> myConstraints;
+};
+
+
/// Message that sends the features which license is checked and valid
class ModelAPI_FeaturesLicenseValidMessage : public Events_Message
{
thePref->prefMgr()->setItemIcon(thePage, QIcon(":pictures/module.png"));
createGeneralTab(thePref, thePage);
createCustomPage(thePref, thePage);
+ updateSketchTab(thePref, thePage);
}
void ModuleBase_Preferences::resetResourcePreferences(SUIT_PreferenceMgr* thePref)
thePref->setItemProperty("indexes", visuIdList, visuId);
}
+void ModuleBase_Preferences::updateSketchTab(ModuleBase_IPrefMgr* thePref, int thePageId)
+{
+ int sketchTab = thePref->addPreference(QObject::tr("Sketch"), thePageId,
+ SUIT_PreferenceMgr::Auto, QString(), QString());
+ int allowChange = thePref->addPreference(
+ QObject::tr("Allow automatic constraint substitution/remove"),
+ sketchTab, SUIT_PreferenceMgr::GroupBox,
+ "Sketch", "allow_change_constraint");
+ thePref->addPreference(QObject::tr("Notify automatic constraint substitution/remove"),
+ allowChange, SUIT_PreferenceMgr::Bool, "Sketch", "notify_change_constraint");
+}
+
void ModuleBase_Preferences::createCustomPage(ModuleBase_IPrefMgr* thePref, int thePageId)
{
SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
/// Retrieve preferences of config prop to default state
static void resetConfigPropPreferences(SUIT_PreferenceMgr* thePref);
+ /// Updates content of preferences for sketch tab
+ static void updateSketchTab(ModuleBase_IPrefMgr* thePref, int thePageId);
+
private:
/// Updates SUIT_ResourceMgr values by Config_PropManager properties
static void updateResourcesByConfig();
#include <QTextCodec>
#include <QWindow>
#include <QScreen>
+#include <QCheckBox>
#include <sstream>
#include <string>
return true;
}
+//**************************************************************
+bool warningAboutConflict(QWidget* theParent, const std::string& theWarningText)
+{
+ QMessageBox aMessageBox(theParent);
+ aMessageBox.setWindowTitle(QObject::tr("Conflicts in constraint"));
+ aMessageBox.setIcon(QMessageBox::Warning);
+ aMessageBox.setText((theWarningText + "\nConstraints will be removed or substituted").c_str());
+
+ QCheckBox* aCheckBox = new QCheckBox;
+
+ aCheckBox->setTristate(false);
+ aCheckBox->setText("switch off the notifications.");
+
+ aMessageBox.setCheckBox(aCheckBox);
+ aMessageBox.setStandardButtons(QMessageBox::Ok);
+
+ aMessageBox.exec();
+
+ if (aCheckBox->isChecked())
+ {
+ ModuleBase_Preferences::resourceMgr()->setValue(SKETCH_TAB_NAME,
+ "notify_change_constraint", false);
+ }
+
+ return true;
+}
+
//**************************************************************
void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures)
{
std::set<FeaturePtr>& theReferencesToDelete,
const std::string& thePrefixInfo = "");
+/// Shows a message box about conflicting constraints.
+/// \param theParent a parent widget for the message box
+/// \param theWarningText text describing the cause of the conflict
+bool MODULEBASE_EXPORT warningAboutConflict(QWidget* theParent, const std::string& theWarningText);
+
/// Converts a list of objects to set of corresponded features. If object is result, it is ignored
/// because the feature only might be removed. But if result is in a parameter group, the feature
/// of this parameter is to be removed
#include <ModuleBase_OperationDescription.h>
#include <ModuleBase_ViewerPrs.h>
#include <ModuleBase_ResultPrs.h>
+#include <ModuleBase_Preferences.h>
#include <ModelAPI_ResultField.h>
#include <ModelAPI_Object.h>
#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
#include <Graphic3d_Texture2Dmanual.hxx>
+#include <SUIT_ResourceMgr.h>
#define FEATURE_ITEM_COLOR "0,0,225"
}
//******************************************************
-void PartSet_Module::onConflictingConstraints()
+void PartSet_Module::onRemoveConflictingConstraints()
{
- const std::set<ObjectPtr>& aConstraints = myOverconstraintListener->conflictingObjects();
- QObjectPtrList aObjectsList;
- std::set<ObjectPtr>::const_iterator aIt;
- for (aIt = aConstraints.cbegin(); aIt != aConstraints.cend(); aIt++) {
- if (mySketchReentrantMgr->isLastAutoConstraint(*aIt))
- aObjectsList.append(*aIt);
+ const std::set<ObjectPtr>& aConstraints = myOverconstraintListener->objectsToRemove();
+ std::set<ObjectPtr>::const_iterator anIt;
+
+ XGUI_Workshop* aWorkshop = getWorkshop();
+ XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
+
+ bool isAllowToNotify = ModuleBase_Preferences::resourceMgr()->booleanValue(SKETCH_TAB_NAME,
+ "notify_change_constraint");
+
+ if (isAllowToNotify) {
+ anIt = aConstraints.begin();
+ std::string aText("Conflict in constraints: \n");
+
+ for (; anIt != aConstraints.end(); anIt++)
+ {
+ ObjectPtr anObject = *anIt;
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+ TCollection_AsciiString aStr(aFeature->name().c_str());
+ std::string aName(aStr.ToCString());
+ aText += aName + "\n";
+ }
+
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+ ModuleBase_Tools::warningAboutConflict(aConnector->desktop(),
+ aText);
}
- if (aObjectsList.size() > 0) {
- XGUI_Workshop* aWorkshop = getWorkshop();
+
+ ModuleBase_Operation* anOp = anOpMgr->currentOperation();
+ if (sketchMgr()->isNestedSketchOperation(anOp)) {
+ std::set<FeaturePtr> aFeatures;
+ for (anIt = aConstraints.cbegin(); anIt != aConstraints.cend(); anIt++)
+ aFeatures.insert(ModelAPI_Feature::feature(*anIt));
+
+ ModelAPI_Tools::removeFeaturesAndReferences(aFeatures);
+ }
+ else {
+ QObjectPtrList anObjectsList;
+ for (anIt = aConstraints.cbegin(); anIt != aConstraints.cend(); anIt++)
+ anObjectsList.append(*anIt);
+
QString aDescription = aWorkshop->contextMenuMgr()->action("DELETE_CMD")->text();
ModuleBase_Operation* anOpAction = new ModuleBase_Operation(aDescription);
- XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
-
- ModuleBase_Operation* anOp = anOpMgr->currentOperation();
- if (sketchMgr()->isNestedSketchOperation(anOp))
- anOp->abort();
anOpMgr->startOperation(anOpAction);
- aWorkshop->deleteFeatures(aObjectsList);
+ aWorkshop->deleteFeatures(anObjectsList);
anOpMgr->commitOperation();
- ModuleBase_Tools::flushUpdated(sketchMgr()->activeSketch());
}
+ ModuleBase_Tools::flushUpdated(sketchMgr()->activeSketch());
}
/// \param theTrsfType type of tranformation
virtual void onViewTransformed(int theTrsfType = 2);
- void onConflictingConstraints();
+ /// Called on remove conflicting constraints
+ void onRemoveConflictingConstraints();
protected slots:
/// Called when previous operation is finished
#include <ModelAPI_Tools.h>
#include <ModelAPI_AttributeString.h>
+// Attention: keep the next include here,
+// otherwise it causes compilation errors at least on Debian 8
+#include <ModuleBase_Preferences.h>
+
#include "PartSet_OverconstraintListener.h"
#include <PartSet_Module.h>
#include <PartSet_SketcherMgr.h>
#include "SketchPlugin_ConstraintHorizontal.h"
#include "SketchPlugin_ConstraintVertical.h"
+#include <SUIT_ResourceMgr.h>
+
#include "Events_Loop.h"
#include <GeomAPI_IPresentable.h>
aLoop->registerListener(this, ModelAPI_EventReentrantMessage::eventId());
aLoop->registerListener(this, SketchPlugin_MacroArcReentrantMessage::eventId());
+ aLoop->registerListener(this, Events_Loop::eventByName(EVENT_REMOVE_CONSTRAINTS));
}
void PartSet_OverconstraintListener::setActive(const bool& theActive)
}
}
}
+ else if (anEventID == Events_Loop::eventByName(EVENT_REMOVE_CONSTRAINTS)) {
+ std::shared_ptr<ModelAPI_CheckConstraintsMessage> aConstraintsMsg =
+ std::dynamic_pointer_cast<ModelAPI_CheckConstraintsMessage>(theMessage);
+ if (aConstraintsMsg.get()) {
+ myObjectsToRemove = aConstraintsMsg->constraints();
+
+ std::set<ObjectPtr>::const_iterator
+ anIt = myObjectsToRemove.begin(), aLast = myObjectsToRemove.end();
+
+ PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+
+ for (; anIt != aLast; anIt++)
+ {
+ ObjectPtr anObject = *anIt;
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+ std::string aType = aFeature->getKind();
+ if ((aType == SketchPlugin_ConstraintHorizontal::ID() ||
+ aType == SketchPlugin_ConstraintVertical::ID()) &&
+ !aModule->sketchReentranceMgr()->isLastAutoConstraint(*anIt))
+ myObjectsToRemove.erase(*anIt);
+ }
+
+ if (myObjectsToRemove.empty())
+ return;
+ QTimer::singleShot(5, aModule, SLOT(onRemoveConflictingConstraints()));
+ }
+ }
#ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
aCurrentInfoStr = getObjectsInfo(myConflictingObjects);
qDebug(QString("RESULT: current objects count = %1:%2\n")
bool PartSet_OverconstraintListener::appendConflictingObjects(
const std::set<ObjectPtr>& theConflictingObjects)
{
- std::set<ObjectPtr> aModifiedObjects;
-
- // set error state for new objects and append them in the internal map of objects
- std::set<ObjectPtr>::const_iterator
- anIt = theConflictingObjects.begin(), aLast = theConflictingObjects.end();
- FeaturePtr aFeature;
- bool isHVConstraint = false;
- for (; anIt != aLast; anIt++) {
- ObjectPtr anObject = *anIt;
- if (myConflictingObjects.find(anObject) == myConflictingObjects.end()) { // it is not found
- aModifiedObjects.insert(anObject);
- myConflictingObjects.insert(anObject);
- }
- if (!isHVConstraint) {
- aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
- if (aFeature) {
- std::string aType = aFeature->getKind();
- isHVConstraint = (aType == SketchPlugin_ConstraintHorizontal::ID()) ||
- (aType == SketchPlugin_ConstraintVertical::ID());
+ bool isAllowToChange = ModuleBase_Preferences::resourceMgr()->booleanValue(SKETCH_TAB_NAME,
+ "allow_change_constraint");
+ if (isAllowToChange) {
+ std::set<ObjectPtr> aModifiedObjects;
+
+ // set error state for new objects and append them in the internal map of objects
+ std::set<ObjectPtr>::const_iterator
+ anIt = theConflictingObjects.begin(), aLast = theConflictingObjects.end();
+
+ int aCountOfSimilarConstraints = 0;
+ for (; anIt != aLast; anIt++) {
+ ObjectPtr anObject = *anIt;
+ if (myConflictingObjects.find(anObject) == myConflictingObjects.end()) { // it is not found
+ aModifiedObjects.insert(anObject);
+ myConflictingObjects.insert(anObject);
}
+ else
+ ++aCountOfSimilarConstraints;
}
- }
- bool isUpdated = !aModifiedObjects.empty();
- if (isUpdated)
- redisplayObjects(aModifiedObjects);
- // If the conflicting object is an automatic constraint caused the conflict
- // then it has to be deleted
- if (isHVConstraint) {
- PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
- QTimer::singleShot(5, aModule, SLOT(onConflictingConstraints()));
- }
+ if (theConflictingObjects.size() == aCountOfSimilarConstraints)
+ return false;
- return isUpdated;
+ std::shared_ptr<ModelAPI_CheckConstraintsMessage> aMessage =
+ std::shared_ptr<ModelAPI_CheckConstraintsMessage>(
+ new ModelAPI_CheckConstraintsMessage(
+ Events_Loop::eventByName(EVENT_CHECK_CONSTRAINTS)));
+ aMessage->setConstraints(theConflictingObjects);
+ Events_Loop::loop()->send(aMessage);
+
+ bool isUpdated = !aModifiedObjects.empty();
+ if (isUpdated)
+ redisplayObjects(aModifiedObjects);
+ return isUpdated;
+ }
+ else
+ return false;
}
bool PartSet_OverconstraintListener::repairConflictingObjects(
return myConflictingObjects;
}
+ const std::set<ObjectPtr>& objectsToRemove() const
+ {
+ return myObjectsToRemove;
+ }
+
bool isFullyConstrained() const { return myIsFullyConstrained; }
protected:
ModuleBase_IWorkshop* myWorkshop;
bool myIsActive; /// state if sketch is active
std::set<ObjectPtr> myConflictingObjects;
+ std::set<ObjectPtr> myObjectsToRemove;
bool myIsFullyConstrained; /// state if Solver is fully constrained, DOF = 0
};
<parameter name="part_visualization_study" value="0"/>
<parameter name="part_visualization_script" value="1"/>
</section>
+ <section name="Sketch">
+ <!-- Sketch preferences -->
+ <parameter name="allow_change_constraint" value="true"/>
+ <parameter name="notify_change_constraint" value="true"/>
+ </section>
<section name="Viewer" >
<!-- Viewer preferences -->
<parameter name="face-selection" value="true" />
SketchPlugin_MultiRotation.h
SketchPlugin_MultiTranslation.h
SketchPlugin_Offset.h
+ SketchPlugin_OverConstraintsResolver.h
SketchPlugin_Plugin.h
SketchPlugin_Point.h
SketchPlugin_Projection.h
SketchPlugin_MultiRotation.cpp
SketchPlugin_MultiTranslation.cpp
SketchPlugin_Offset.cpp
+ SketchPlugin_OverConstraintsResolver.cpp
SketchPlugin_Plugin.cpp
SketchPlugin_Point.cpp
SketchPlugin_Projection.cpp
--- /dev/null
+// Copyright (C) 2014-2021 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include <SketchPlugin_OverConstraintsResolver.h>
+
+#include <Events_Loop.h>
+
+#include <ModelAPI_Attribute.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Tools.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_ConstraintHorizontal.h>
+#include <SketchPlugin_ConstraintVertical.h>
+#include <SketchPlugin_Point.h>
+
+static SketchPlugin_OverConstraintsResolver* myConstResolver =
+ new SketchPlugin_OverConstraintsResolver;
+
+SketchPlugin_OverConstraintsResolver::SketchPlugin_OverConstraintsResolver()
+{
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_CHECK_CONSTRAINTS));
+}
+
+void SketchPlugin_OverConstraintsResolver::setConstraints(
+ const std::set<ObjectPtr>& theConstraints)
+{
+ myConstraints = theConstraints;
+}
+
+bool SketchPlugin_OverConstraintsResolver::perform()
+{
+ bool hasConflicts = false;
+ hasConflicts |= checkArcsAboutTangentialConflict();
+ hasConflicts |= checkHorizontalOrVerticalConflict();
+ return hasConflicts;
+}
+
+bool SketchPlugin_OverConstraintsResolver::checkHorizontalOrVerticalConflict()
+{
+ std::set<ObjectPtr>::const_iterator
+ anIt = myConstraints.begin(), aLast = myConstraints.end();
+ bool isHVConstraint = false;
+ FeaturePtr aFeature;
+ for (; anIt != aLast; anIt++) {
+ ObjectPtr anObject = *anIt;
+ if (!isHVConstraint) {
+ aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+ if (aFeature) {
+ std::string aType = aFeature->getKind();
+ if ((aType == SketchPlugin_ConstraintHorizontal::ID()) ||
+ (aType == SketchPlugin_ConstraintVertical::ID()))
+ {
+ myConstraintsToRemove.insert(*anIt);
+ isHVConstraint = true;
+ }
+ }
+ }
+ }
+ return isHVConstraint;
+}
+
+bool SketchPlugin_OverConstraintsResolver::checkArcsAboutTangentialConflict()
+{
+ bool isConflictsFound = false;
+
+ std::set<ObjectPtr>::const_iterator
+ anIt = myConstraints.begin(), aLast = myConstraints.end();
+ for (; anIt != aLast; anIt++) {
+ ObjectPtr anObject = *anIt;
+ ConstraintPtr aConstain =
+ std::dynamic_pointer_cast<SketchPlugin_Constraint>(anObject);
+ if (aConstain.get()) {
+ std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttrA = aConstain->refattr(
+ aConstain->ENTITY_A());
+ std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttrB = aConstain->refattr(
+ aConstain->ENTITY_B());
+ if (!aRefAttrA || !aRefAttrB)
+ continue;
+
+ FeaturePtr aFeatureA = ModelAPI_Feature::feature(aRefAttrA->object());
+ FeaturePtr aFeatureB = ModelAPI_Feature::feature(aRefAttrB->object());
+
+ if (aFeatureA && aFeatureA->getKind() == SketchPlugin_Arc::ID() &&
+ aFeatureB && aFeatureB->getKind() == SketchPlugin_Arc::ID()) {
+
+ std::shared_ptr<ModelAPI_Attribute> anAttrStrA = aFeatureA->attribute(
+ SketchPlugin_Arc::START_ID());
+ std::shared_ptr<ModelAPI_Attribute> anAttrEndA = aFeatureA->attribute(
+ SketchPlugin_Arc::END_ID());
+ std::shared_ptr<ModelAPI_Attribute> anAttrStrB = aFeatureB->attribute(
+ SketchPlugin_Arc::START_ID());
+ std::shared_ptr<ModelAPI_Attribute> anAttrEndB = aFeatureB->attribute(
+ SketchPlugin_Arc::END_ID());
+ std::shared_ptr<ModelAPI_Attribute> anAttrCenA = aFeatureA->attribute(
+ SketchPlugin_Arc::CENTER_ID());
+ std::shared_ptr<ModelAPI_Attribute> anAttrCenB = aFeatureB->attribute(
+ SketchPlugin_Arc::CENTER_ID());
+
+ bool isCoincident = false;
+ bool isCoincidentAtCenter = false;
+ std::set<FeaturePtr> aTangentConstraints;
+
+ std::set<FeaturePtr> aFeatures;
+ std::map<FeaturePtr, std::set<FeaturePtr> > aFeaturesMap;
+ aFeatures.insert(aFeatureA);
+ aFeatures.insert(aFeatureB);
+ ModelAPI_Tools::findAllReferences(aFeatures, aFeaturesMap);
+
+ std::set<FeaturePtr> aFeaturesA = aFeaturesMap[aFeatureA];
+ std::set<FeaturePtr> aFeaturesB = aFeaturesMap[aFeatureB];
+
+ for (auto aFeatIter = aFeaturesA.begin(); aFeatIter != aFeaturesA.end(); ++aFeatIter) {
+ if (aFeaturesB.find(aFeatIter.operator*()) != aFeaturesB.end()){
+ const std::string& aType = (*aFeatIter)->getKind();
+ if (aType == SketchPlugin_ConstraintCoincidence::ID()) {
+ ConstraintPtr aCoincidence =
+ std::dynamic_pointer_cast<SketchPlugin_ConstraintCoincidence>(*aFeatIter);
+ std::set<AttributePtr> anAttrSet;
+ anAttrSet.insert(aCoincidence->refattr(aCoincidence->ENTITY_A())->attr());
+ anAttrSet.insert(aCoincidence->refattr(aCoincidence->ENTITY_B())->attr());
+ isCoincident |= ((anAttrSet.find(anAttrStrA) != anAttrSet.end() ||
+ anAttrSet.find(anAttrEndA) != anAttrSet.end()) &&
+ (anAttrSet.find(anAttrStrB) != anAttrSet.end() ||
+ anAttrSet.find(anAttrEndB) != anAttrSet.end()));
+ isCoincidentAtCenter |= (anAttrSet.find(anAttrCenA) != anAttrSet.end() &&
+ anAttrSet.find(anAttrCenB) != anAttrSet.end());
+ }
+ else if (aType == SketchPlugin_ConstraintTangent::ID()) {
+ aTangentConstraints.insert(*aFeatIter);
+ }
+ }
+ }
+
+ if (isCoincident && isCoincidentAtCenter && !aTangentConstraints.empty()) {
+ isConflictsFound = true;
+ myConstraintsToRemove.insert(aTangentConstraints.begin(), aTangentConstraints.end());
+ }
+ }
+ }
+ }
+
+ return isConflictsFound;
+}
+
+void SketchPlugin_OverConstraintsResolver::processEvent(
+ const std::shared_ptr<Events_Message>& theMessage)
+{
+ Events_ID anEventID = theMessage->eventID();
+ if (anEventID == Events_Loop::eventByName(EVENT_CHECK_CONSTRAINTS)) {
+ std::shared_ptr<ModelAPI_CheckConstraintsMessage> aConstraintsMsg =
+ std::dynamic_pointer_cast<ModelAPI_CheckConstraintsMessage>(theMessage);
+ if (aConstraintsMsg.get()) {
+ myConstraintsToRemove.clear();
+ myConstraints = aConstraintsMsg->constraints();
+ if (perform())
+ {
+ std::shared_ptr<ModelAPI_CheckConstraintsMessage> aMessage =
+ std::shared_ptr<ModelAPI_CheckConstraintsMessage>(
+ new ModelAPI_CheckConstraintsMessage(
+ Events_Loop::eventByName(EVENT_REMOVE_CONSTRAINTS)));
+ aMessage->setConstraints(myConstraintsToRemove);
+ Events_Loop::loop()->send(aMessage);
+ }
+ }
+ }
+}
--- /dev/null
+// Copyright (C) 2014-2021 CEA/DEN, EDF R&D
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SketchPlugin_OverConstraintsResolver_H_
+#define SketchPlugin_OverConstraintsResolver_H_
+
+#include "SketchPlugin.h"
+
+#include <Events_Listener.h>
+
+#include <ModelAPI_Object.h>
+
+#include <set>
+
+class SketchPlugin_OverConstraintsResolver : public Events_Listener
+{
+public:
+ SketchPlugin_OverConstraintsResolver();
+
+ /// Redefinition of Events_Listener method
+ void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ virtual bool groupMessages() { return true; }
+
+protected:
+ /// Perform algorithm
+ bool perform();
+
+ /// Set set of constraints to check
+ void setConstraints(const std::set<ObjectPtr>& theConstraints);
+
+ /// Check arcs in sketch about tangential conflict
+ bool checkArcsAboutTangentialConflict();
+
+ /// Check lines in sketch about horizontal or vertical conflict
+ bool checkHorizontalOrVerticalConflict();
+
+private:
+ std::set<ObjectPtr> myConstraints;
+ std::set<ObjectPtr> myConstraintsToRemove;
+};
+#endif
<parameter name="part_visualization_study" value="0"/>
<parameter name="part_visualization_script" value="1"/>
</section>
+ <section name="Sketch">
+ <!-- Sketch preferences -->
+ <parameter name="allow_change_constraint" value="true"/>
+ <parameter name="notify_change_constraint" value="true"/>
+ </section>
<section name="Viewer" >
<!-- Viewer preferences -->
<parameter name="background" value="bt=2;fn=;tm=0;ts=false;c1=#cddbff;c2=#698fff;gt=1;gr=" />
<parameter name="winapplication" value="C:\Program Files\Internet Explorer\iexplore.exe" />
<parameter name="application" value="/usr/bin/mozilla" />
</section>
-
</document>