const std::shared_ptr<GeomAPI_Shape>& theWire,
std::list<std::shared_ptr<GeomAPI_Shape> >& theResultFaces)
{
- std::shared_ptr<GeomAPI_PlanarEdges> aWire = std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
- if(!aWire)
- return;
- // Filter wires, return only faces.
std::list<std::shared_ptr<GeomAPI_Shape> > aFilteredWires;
- createFaces(theOrigin, theDirX, theNorm,
- aWire->getEdges(), theResultFaces, aFilteredWires);
+ std::shared_ptr<GeomAPI_PlanarEdges> aWire =
+ std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(theWire);
+ if(aWire) {
+ // Filter wires, return only faces.
+ createFaces(theOrigin, theDirX, theNorm,
+ aWire->getEdges(), theResultFaces, aFilteredWires);
+
+ return;
+ } else { // it may be only one circle
+ std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(theWire);
+ if (anEdge) {
+ std::list<std::shared_ptr<GeomAPI_Shape> > aList;
+ aList.push_back(anEdge);
+ createFaces(theOrigin, theDirX, theNorm,
+ aList, theResultFaces, aFilteredWires);
+ }
+ }
}
//the attribute initialized state should be changed by sendAttributeUpdated only
//myIsInitialized = true;
+ owner()->data()->sendAttributeUpdated(this);
+
std::string aSelName = namingName();
if(!aSelName.empty())
TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name
//selectSubShape("EDGE", "Extrusion_1/TopFace|Extrusion_1/LateralFace_1");
//selectSubShape("EDGE", "Sketch_1/Edge_6");
#endif
- owner()->data()->sendAttributeUpdated(this);
}
std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
break;
} else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) {
aNewBody = createGroup(theFeature->data(), aResIndex);
+ } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) {
+ theFeature->attributeChanged("expression"); // just produce a value
+ break;
} else {
Events_Error::send(std::string("Unknown type of result is found in the document:") +
TCollection_AsciiString(aGroup->Get()).ToCString());
for(aFIter = myJustCreatedOrUpdated.begin(); aFIter != myJustCreatedOrUpdated.end(); aFIter++)
{
FeaturePtr aF = std::dynamic_pointer_cast<ModelAPI_Feature>(*aFIter);
- if (aF && aF->getKind() == "Extrusion") {
+ if (aF && aF->data().get() && aF->getKind() == "Extrusion") {
AttributeSelectionListPtr aBase = aF->selectionList("base");
if (aBase.get()) {
for(int a = aBase->size() - 1; a >= 0; a--) {
ModuleBase_WidgetValidated.cpp
ModuleBase_WidgetExprEditor.cpp
ModuleBase_ParamSpinBox.cpp
+ ModuleBase_SelectionValidator.cpp
)
SET(PROJECT_LIBRARIES
}
myOriginalShape = aShapePtr->impl<TopoDS_Shape>();
if (!myOriginalShape.IsNull()) {
- Set(aShapePtr->impl<TopoDS_Shape>());
+ Set(myOriginalShape);
AIS_Shape::Compute(thePresentationManager, thePresentation, theMode);
}
}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModuleBase_SelectionValidator.cpp
+// Created: 8 Jul 2014
+// Author: Vitaly SMETANNIKOV
+
+#include <ModuleBase_SelectionValidator.h>
+
+bool ModuleBase_SelectionValidator::isValid(const ModuleBase_ISelection* theSelection,
+ const std::list<std::string>& theArguments) const
+{
+ return isValid(theSelection);
+}
public:
/// Returns True if selection is valid
/// \param theSelection selection instance
- virtual bool isValid(const ModuleBase_ISelection* theSelection) const = 0;
+ /// \param theArguments list of arguments
+ virtual MODULEBASE_EXPORT bool isValid(const ModuleBase_ISelection* theSelection,
+ const std::list<std::string>& theArguments) const;
+ protected:
/// Returns True if selection is valid
/// \param theSelection selection instance
- /// \param theArguments list of arguments
- virtual bool isValid(const ModuleBase_ISelection* theSelection,
- const std::list<std::string>& theArguments) const
- {
- return isValid(theSelection);
- }
+ virtual bool isValid(const ModuleBase_ISelection* theSelection) const = 0;
};
#endif
{
activateShapeSelection();
QObjectPtrList anEmptyList;
+ // This method will call Selection changed event which will call onSelectionChanged
+ // To clear mySelection, myListControl and storeValue()
+ // So, we don't need to call it
myWorkshop->setSelected(anEmptyList);
- // Clear mySelection, myListControl and storeValue()
- onSelectionChanged();
}
//********************************************************************
#include <ModelAPI_Session.h>
#include <ModelAPI_Validator.h>
#include <ModelAPI_AttributeValidator.h>
+#include <ModelAPI_Events.h>
#include <SelectMgr_ListIteratorOfListOfFilter.hxx>
#include <SelectMgr_EntityOwner.hxx>
anAttribute->blockSetInitialized(isAttributeBlocked);
aLoop->activateFlushes(true);
+ // In particular case the results are deleted and called as redisplayed inside of this
+ // highlight-selection, to they must be flushed as soon as possible.
+ // Example: selection of group-vertices subshapes with shift pressend on body. Without
+ // these 4 lines below the application crashes because of left presentations on
+ // removed results still in the viewer.
+ static Events_ID aDeletedEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+ static Events_ID aRedispEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+ aLoop->flush(aDeletedEvent);
+ aLoop->flush(aRedispEvent);
+
return aValid;
}
<plugin>
<workbench id="Part">
<group id="Parameters">
- <feature id="Parameter" title="New Variable" tooltip="Creates a variable" icon=":pictures/expression.png">
+ <feature id="Parameter" title="Parameter" tooltip="Create a parameter" icon=":pictures/expression.png">
<stringvalue id="variable" label="Name" icon=":pictures/expression.png">
<validator id="Parameters_VariableValidator"/>
</stringvalue>
myCoinsideLines.clear();
ModuleBase_ISelection* aSelection = myModule->workshop()->selection();
- NCollection_List<TopoDS_Shape> aShapeList;
- std::list<ObjectPtr> aObjectsList;
- aSelection->selectedShapes(aShapeList, aObjectsList);
bool aIsDetach = false;
-
- // Check that selected shape is not attribute
- // if at least a one shape is attribute then we can not add auxiliary item
bool hasAttribute = false;
- if (aShapeList.Extent() > 0) {
- NCollection_List<TopoDS_Shape>::Iterator aIt(aShapeList);
- std::list<ObjectPtr>::const_iterator aItObj;
- TopoDS_Shape aShape;
- ObjectPtr aObj;
- ResultPtr aResult;
- for (aItObj = aObjectsList.cbegin(); aIt.More(); aIt.Next(), aItObj++) {
- aShape = aIt.Value();
- aObj = (*aItObj);
- aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
- if (aResult.get() != NULL) {
- if (!aShape.IsEqual(aResult->shape()->impl<TopoDS_Shape>())) {
- hasAttribute = true;
- break;
- }
- }
+ bool hasFeature = false;
+
+ QList<ModuleBase_ViewerPrs> aPrsList = aSelection->getSelected();
+ TopoDS_Shape aShape;
+ ResultPtr aResult;
+ FeaturePtr aFeature;
+ foreach(ModuleBase_ViewerPrs aPrs, aPrsList) {
+ aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aPrs.object());
+ if (aResult.get() != NULL) {
+ aShape = aPrs.shape();
+ if (aShape.IsEqual(aResult->shape()->impl<TopoDS_Shape>()))
+ hasFeature = true;
+ else
+ hasAttribute = true;
+ } else {
+ aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aPrs.object());
+ hasFeature = (aFeature.get() != NULL);
}
}
- if (aShapeList.Extent() == 1) {
- TopoDS_Shape aShape = aShapeList.First();
- if (aShape.ShapeType() == TopAbs_VERTEX) {
+ if (aPrsList.size() == 1) {
+ TopoDS_Shape aShape = aPrsList.first().shape();
+ if ((!aShape.IsNull()) && aShape.ShapeType() == TopAbs_VERTEX) {
// Find 2d coordinates
FeaturePtr aSketchFea = myModule->sketchMgr()->activeSketch();
if (aSketchFea->getKind() == SketchPlugin_Sketch::ID()) {
std::shared_ptr<GeomAPI_Pnt2d> aSelPnt = PartSet_Tools::convertTo2D(aSketchFea, aPnt3d);
// Find coincident in these coordinates
- ObjectPtr aObj = aObjectsList.front();
+ ObjectPtr aObj = aPrsList.first().object();
FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
const std::set<AttributePtr>& aRefsList = aFeature->data()->refsToMe();
std::set<AttributePtr>::const_iterator aIt;
}
}
}
- QObjectPtrList aObjects = aSelection->selectedPresentations();
- if ((!aIsDetach) && (aObjects.size() > 0)) {
- bool hasFeature = false;
- FeaturePtr aFeature;
- foreach (ObjectPtr aObject, aObjects) {
- aFeature = ModelAPI_Feature::feature(aObject);
- if (aFeature.get() != NULL) {
- hasFeature = true;
- }
- }
- if (hasFeature && (!hasAttribute))
- theMenu->addAction(theStdActions["DELETE_CMD"]);
+ if ((!aIsDetach) && hasFeature) {
+ theMenu->addAction(theStdActions["DELETE_CMD"]);
}
if (hasAttribute)
return true;
if (aSelectedObj.count() == 0)
return false;
+ // avoid delete of the objects, which are not belong to the current sketch
+ // in order to do not delete results of other sketches
+ QObjectPtrList aSketchObjects;
+ QObjectPtrList::const_iterator anIt = aSelectedObj.begin(), aLast = aSelectedObj.end();
+ for ( ; anIt != aLast; anIt++) {
+ ObjectPtr anObject = *anIt;
+ if (mySketchMgr->isObjectOfSketch(anObject))
+ aSketchObjects.append(anObject);
+ }
+ // if the selection contains only local selected presentations from other sketches,
+ // the Delete operation should not be done at all
+ if (aSketchObjects.size() == 0)
+ return true;
+
// the active nested sketch operation should be aborted unconditionally
if (isNestedOp)
anOperation->abort();
// when sketch operation is active
std::set<FeaturePtr> anIgnoredFeatures;
anIgnoredFeatures.insert(mySketchMgr->activeSketch());
- aWorkshop->deleteFeatures(aSelectedObj, anIgnoredFeatures);
+ aWorkshop->deleteFeatures(aSketchObjects, anIgnoredFeatures);
// 5. stop operation
aWorkshop->displayer()->updateViewer();
get2dPoint(theWnd, theEvent, myCurrentPoint);
myDragDone = false;
launchEditing();
+ // Init flyout point for radius rotation
+ FeaturePtr aFeature = myCurrentSelection.begin().key();
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+ if (aSPFeature->getKind() == SketchPlugin_ConstraintRadius::ID()) {
+ DataPtr aData = aSPFeature->data();
+ AttributePtr aAttr = aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT());
+ std::shared_ptr<GeomDataAPI_Point2D> aFPAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aAttr);
+ aFPAttr->setValue(myCurrentPoint.myCurX, myCurrentPoint.myCurY);
+ }
} else if (isSketchOpe && isEditing) {
// If selected another object commit current result
return aCanDisplay;
}
+bool PartSet_SketcherMgr::isObjectOfSketch(const ObjectPtr& theObject) const
+{
+ bool isFoundObject = false;
+
+ FeaturePtr anObjectFeature = ModelAPI_Feature::feature(theObject);
+ if (anObjectFeature.get()) {
+ int aSize = myCurrentSketch->numberOfSubs();
+ for (int i = 0; i < myCurrentSketch->numberOfSubs() && !isFoundObject; i++) {
+ FeaturePtr aCurrentFeature = myCurrentSketch->subFeature(i);
+ isFoundObject = myCurrentSketch->subFeature(i) == anObjectFeature;
+ }
+ }
+ return isFoundObject;
+}
void PartSet_SketcherMgr::onPlaneSelected(const std::shared_ptr<GeomAPI_Pln>& thePln)
{
/// Returns state of constraints showing flag
bool isConstraintsShown() const { return myIsConstraintsShown; }
+ /// Returns true if the object is a current sketch sub feature of a result of the feature
+ /// \param theObject an object
+ /// \return boolean value
+ bool isObjectOfSketch(const ObjectPtr& theObject) const;
+
/// Saves the current selection in the viewer into an internal container
/// It obtains the selected attributes. The highlighted objects can be processes as the selected ones
/// \param theHighlightedUse a boolean flag
//! A class to validate a selection for Distance constraint operation
class PartSet_DistanceSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Length constraint operation
class PartSet_LengthSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Perpendicular constraint operation
class PartSet_PerpendicularSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Parallel constraint operation
class PartSet_ParallelSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Radius constraint operation
class PartSet_RadiusSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Rigid constraint operation
class PartSet_RigidSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for coincedence constraint operation
class PartSet_CoincidentSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Horizontal and Vertical constraints operation
class PartSet_HVDirSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Tangential constraints operation
class PartSet_TangentSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
//! A class to validate a selection for Fillet constraints operation
class PartSet_FilletSelection : public ModuleBase_SelectionValidator
{
- public:
+ protected:
PARTSET_EXPORT virtual bool isValid(const ModuleBase_ISelection* theSelection) const;
};
// the external feature should be removed with all references, sketch feature should be ignored
std::set<FeaturePtr> anIgnoredFeatures;
anIgnoredFeatures.insert(sketch());
+ // the current feature should be ignored, because it can use the external feature in the
+ // attributes and, therefore have a references to it. So, the delete functionality tries
+ // to delete this feature. Test case is creation of a constraint on external point,
+ // use in this control after an external point, the point of the sketch.
+ anIgnoredFeatures.insert(myFeature);
XGUI_Workshop::deleteFeatures(anObjects, anIgnoredFeatures);
}
myExternalObject = ObjectPtr();
modeler.begin()
mybase.setValue( mylength, 100 )
-mybox.setSize( 20 )
+mybox.setSize( 80 )
modeler.end()
import ModelAPI
from macros.box.feature import BoxFeature
-from macros.cylinder.feature import CylinderFeature
class PythonFeaturesPlugin(ModelAPI.ModelAPI_Plugin):
if theFeatureID == BoxFeature.ID():
aFeature = BoxFeature().__disown__()
- elif theFeatureID == CylinderFeature.ID():
- aFeature = CylinderFeature().__disown__()
-
else:
raise StandardError("No such feature %s" % theFeatureID)
<plugin>
<source path="../addons/macros/box/widget.xml"/>
- <source path="../addons/macros/cylinder/widget.xml"/>
</plugin>
+++ /dev/null
-"""Cylinder macro-feature
-Authors: Daniel Brunier-Coulin
-Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-"""
-
-import modeler
-import geom
-
-
-class CylinderFeature(modeler.Feature):
-
-
-# Initializations
-
- def __init__(self):
- modeler.Feature.__init__(self)
-
- @staticmethod
- def ID():
- return "Cylinder"
-
- @staticmethod
- def RADIUS_ID():
- return "radius"
-
- @staticmethod
- def LENGTH_ID():
- return "length"
-
- def getKind(self):
- return CylinderFeature.ID()
-
-
-# Creation of the cylinder at default size
-
- def initAttributes(self):
-
- # Creating the input arguments of the feature
- self.addRealInput( self.RADIUS_ID() )
- self.addRealInput( self.LENGTH_ID() )
-
- # Creating the base of the cylinder with unit values
- mypart = modeler.activeDocument()
- xoy = modeler.defaultPlane("XOY")
-
- self.base = modeler.addSketch( mypart, xoy )
- circle = self.base.addCircle( 0, 0, 1)
-
- # Setting the radius of the base with default values
- self.radius = self.base.setRadius( circle.result(), 10 ) # Keeps the constraint for edition
-
- # Creating the extrusion (the cylinder) at default size
- self.cyl = modeler.addExtrusion( mypart, self.base.selectFace(), 50 )
-
-
-# Edition of the cylinder at user size
-
- def execute(self):
- # Retrieving the user inputs
- radius = self.getRealInput( self.RADIUS_ID() )
- length = self.getRealInput( self.LENGTH_ID() )
-
- # Editing the cylinder
- self.base.setValue( self.radius, radius )
- self.cyl.setSize( length )
-
- # Publishing the result
- self.addResult( self.cyl.result() )
\ No newline at end of file
+++ /dev/null
-<source>
- <workbench id="Macros" document="Part">
- <group id="Samples">
-
- <feature id="Cylinder" title="Cylinder" tooltip="Creates a cylinder on the Z axis by extruding a circle" icon=":pictures/part_ico.png">
- <doublevalue id="radius" label="Radius: " min="0" step="1.0" default="10" tooltip="Sets the cylinder radius">
- <validator id="GeomValidators_Positive"/>
- </doublevalue>
- <doublevalue id="length" label="Length: " min="0" step="1.0" default="50" tooltip="Sets the cylinder length">
- <validator id="GeomValidators_Positive"/>
- </doublevalue>
- </feature>
-
- </group>
- </workbench>
-</source>
#include <GeomAPI_Circ.h>
#include <GeomAPI_Circ2d.h>
#include <GeomAPI_Dir.h>
+#include <GeomAPI_XY.h>
#include <GeomAPI_XYZ.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomDataAPI_Dir.h>
#include <Config_PropManager.h>
+const double tolerance = 1.e-7;
+
SketchPlugin_ConstraintRadius::SketchPlugin_ConstraintRadius()
{
+ myFlyoutUpdate = false;
}
void SketchPlugin_ConstraintRadius::initAttributes()
if (!aData->isValid())
return;
- std::shared_ptr<ModelAPI_AttributeRefAttr> aRef = std::dynamic_pointer_cast<
- ModelAPI_AttributeRefAttr>(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
- if (!aFeature)
- return;
- std::string aCenterAttrName;
- if (aFeature->getKind() == SketchPlugin_Circle::ID())
- aCenterAttrName = SketchPlugin_Circle::CENTER_ID();
- else if (aFeature->getKind() == SketchPlugin_Arc::ID())
- aCenterAttrName = SketchPlugin_Arc::CENTER_ID();
- std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
- GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
- std::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
-
- // The specified delta applied on the circle curve,
- // so it will be scaled due to distance between flyout and center points
+ myFlyoutUpdate = true;
std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr = std::dynamic_pointer_cast<
GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
- std::shared_ptr<GeomAPI_Pnt2d> aFlyout = aFlyoutAttr->pnt();
-
- std::shared_ptr<ModelAPI_AttributeDouble> aRadius = std::dynamic_pointer_cast<
- ModelAPI_AttributeDouble>(aData->attribute(SketchPlugin_Constraint::VALUE()));
- double aScale = aFlyout->distance(aCenter) / aRadius->value();
-
- std::shared_ptr<GeomAPI_Circ2d> aCircle(new GeomAPI_Circ2d(aCenter, aFlyout));
- aFlyout->setX(aFlyout->x() + aScale * theDeltaX);
- aFlyout->setY(aFlyout->y() + aScale * theDeltaY);
- aFlyout = aCircle->project(aFlyout);
-
- aFlyoutAttr->setValue(aFlyout->x(), aFlyout->y());
+ aFlyoutAttr->setValue(aFlyoutAttr->x() + theDeltaX, aFlyoutAttr->y() + theDeltaY);
+ myFlyoutUpdate = false;
}
void SketchPlugin_ConstraintRadius::attributeChanged(const std::string& theID) {
aValueAttr->setValue(aRadius);
}
}
+ } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
+ // Recalculate flyout point in local coordinates of the circle (or arc):
+ // coordinates are calculated according to center of the shape
+ std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
+
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aRefAttr || !aRefAttr->isObject())
+ return;
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ if (!aFeature || (aFeature->getKind() != SketchPlugin_Arc::ID() &&
+ aFeature->getKind() != SketchPlugin_Circle::ID()))
+ return;
+
+ std::string aCenterAttrName;
+ if (aFeature->getKind() == SketchPlugin_Circle::ID())
+ aCenterAttrName = SketchPlugin_Circle::CENTER_ID();
+ else if (aFeature->getKind() == SketchPlugin_Arc::ID())
+ aCenterAttrName = SketchPlugin_Arc::CENTER_ID();
+ std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<
+ GeomDataAPI_Point2D>(aFeature->data()->attribute(aCenterAttrName));
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter = aCenterAttr->pnt();
+ std::shared_ptr<ModelAPI_AttributeDouble> aRadius = std::dynamic_pointer_cast<
+ ModelAPI_AttributeDouble>(attribute(SketchPlugin_Constraint::VALUE()));
+
+ std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
+ double aDist = aFlyoutPnt->distance(aCenter);
+ if (aDist < tolerance)
+ return;
+
+ myFlyoutUpdate = true;
+ std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aCenter->xy());
+ aFlyoutAttr->setValue(aFlyoutDir->x(), aFlyoutDir->y());
+ myFlyoutUpdate = false;
}
}
/// Checks and gets the radius of referenced circle (or arc) otherwise returns -1.
/// \param theCircData the found referenced circle returned by this method
double circleRadius(std::shared_ptr<ModelAPI_Feature>& theCirc);
+
+private:
+ bool myFlyoutUpdate; ///< to avoid cyclic dependencies on automatic updates of flyout point
};
#endif
<!-- SketchConstraintCoincedence -->
<feature id="SketchConstraintCoincidence" title="Coincident" tooltip="Create constraint for the coincidence of two points" icon=":icons/coincedence.png">
- <sketch_shape_selector id="ConstraintEntityA" label="First point" tooltip="Select a first point" shape_types="vertex"/>
+ <sketch_shape_selector id="ConstraintEntityA" label="First point" tooltip="Select a first point" shape_types="vertex">
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
+ </sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB" label="Second point" tooltip="Select a second point" shape_types="vertex">
<validator id="PartSet_DifferentObjects"/>
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
</sketch_shape_selector>
<validator id="PartSet_CoincidentSelection"/>
</feature>
icon=":icons/equal.png">
<sketch_shape_selector id="ConstraintEntityA"
label="First object" tooltip="Select line, circle or arc" shape_types="edge">
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityB"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB"
label="Second object" tooltip="Select line, circle or arc" shape_types="edge">
<validator id="SketchPlugin_EqualAttr" parameters="ConstraintEntityA"/>
<validator id="PartSet_DifferentObjects"/>
+ <validator id="SketchPlugin_ExternalValidator" parameters="ConstraintEntityA"/>
</sketch_shape_selector>
</feature>
<feature id="SketchConstraintFillet" title="Fillet" tooltip="Create constraint defining fillet between two objects" icon=":icons/fillet.png">
<sketch_shape_selector id="ConstraintEntityA"
label="First object" tooltip="Select line or arc" shape_types="edge">
+ <validator id="PartSet_DifferentObjects"/>
</sketch_shape_selector>
<sketch_shape_selector id="ConstraintEntityB"
label="Second object" tooltip="Select line or arc" shape_types="edge">
+ <validator id="PartSet_DifferentObjects"/>
</sketch_shape_selector>
<doublevalue label="Value" tooltip="Fillet radius" id="ConstraintValue" min="0">
std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
for (; aCIter != mySlvsConstraints.end(); aCIter++) {
Slvs_Constraint aConstraint = myStorage->getConstraint(*aCIter);
- aConstraint.valA = aValue;
+ if (aValueAttr)
+ aConstraint.valA = aValue;
Slvs_hEntity* aCoeffs[6] = {
&aConstraint.ptA, &aConstraint.ptB,
&aConstraint.entityA, &aConstraint.entityB,
getType(), myGroup->getWorkplaneId(), aValue, aPoint[0], aPoint[1], aLine, SLVS_E_UNKNOWN);
aConstraint.h = myStorage->addConstraint(aConstraint);
mySlvsConstraints.push_back(aConstraint.h);
- adjustConstraint();
-}
-void SketchSolver_ConstraintDistance::adjustConstraint()
-{
+ // Adjust point-line distance
if (getType() != SLVS_C_PT_LINE_DISTANCE)
return;
}
}
}
-
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
virtual void process();
- /// \brief Verifies the sign of the distance between line and point and change it if necessary
- virtual void adjustConstraint();
-
private:
int myType; ///< type of constraint (applicable: SLVS_C_PT_PT_DISTANCE, SLVS_C_PT_LINE_DISTANCE)
};
std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
std::set<ObjectPtr> aFeatures = anUpdateMsg->objects();
+ // Shows the message has at least one feature applicable for solver
+ bool hasProperFeature = false;
+
bool isMovedEvt = theMessage->eventID()
== Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
if (isMovedEvt) {
for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
std::shared_ptr<SketchPlugin_Feature> aSFeature =
std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (aSFeature)
+ if (aSFeature) {
moveEntity(aSFeature);
+ hasProperFeature = true;
+ }
}
} else {
std::set<ObjectPtr>::iterator aFeatIter;
if (aFeatureKind.compare(SketchPlugin_Sketch::ID()) == 0) {
std::shared_ptr<ModelAPI_CompositeFeature> aSketch = std::dynamic_pointer_cast<
ModelAPI_CompositeFeature>(aFeature);
- changeWorkplane(aSketch);
+ hasProperFeature = changeWorkplane(aSketch) || hasProperFeature;
}
}
// then get anything but not the sketch
aComplexConstraints.insert(aFeature);
continue;
}
- changeConstraintOrEntity(aFeature);
+ hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature;
}
// processing remain constraints
aFeatIter = aComplexConstraints.begin();
std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
if (!aFeature)
continue;
- changeConstraintOrEntity(aFeature);
+ hasProperFeature = changeConstraintOrEntity(aFeature) || hasProperFeature;
}
}
// Solve the set of constraints
- resolveConstraints(isMovedEvt); // send update for movement in any case
+ if (hasProperFeature)
+ resolveConstraints(isMovedEvt); // send update for movement in any case
} else if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)) {
std::shared_ptr<ModelAPI_ObjectDeletedMessage> aDeleteMsg =
std::dynamic_pointer_cast<ModelAPI_ObjectDeletedMessage>(theMessage);
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
+#include <math.h>
+
SketchSolver_ConstraintRigid::SketchSolver_ConstraintRigid(FeaturePtr theFeature)
: SketchSolver_Constraint(),
myBaseFeature(theFeature)
void SketchSolver_ConstraintRigid::fixLine(const Slvs_Entity& theLine)
{
Slvs_Constraint anEqual;
- if (isUsedInEqual(theLine, anEqual)) {
+ if (isAxisParallel(theLine)) {
+ // Fix one point and a line length
+ Slvs_hConstraint aFixed;
+ if (!myStorage->isPointFixed(theLine.point[0], aFixed, true) &&
+ !myStorage->isPointFixed(theLine.point[1], aFixed, true))
+ fixPoint(theLine.point[0]);
+ if (!isUsedInEqual(theLine, anEqual)) {
+ // Calculate distance between points on the line
+ double aCoords[4];
+ for (int i = 0; i < 2; i++) {
+ Slvs_Entity aPnt = myStorage->getEntity(theLine.point[i]);
+ for (int j = 0; j < 2; j++) {
+ Slvs_Param aParam = myStorage->getParameter(aPnt.param[j]);
+ aCoords[2*i+j] = aParam.val;
+ }
+ }
+ double aLength = sqrt((aCoords[2] - aCoords[0]) * (aCoords[2] - aCoords[0]) +
+ (aCoords[3] - aCoords[1]) * (aCoords[3] - aCoords[1]));
+ // fix line length
+ Slvs_Constraint aDistance = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
+ SLVS_C_PT_PT_DISTANCE, myGroup->getWorkplaneId(), aLength,
+ theLine.point[0], theLine.point[1], SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
+ aDistance.h = myStorage->addConstraint(aDistance);
+ mySlvsConstraints.push_back(aDistance.h);
+ }
+ return;
+ }
+ else if (isUsedInEqual(theLine, anEqual)) {
// Check another entity of Equal is already fixed
Slvs_hEntity anOtherEntID = anEqual.entityA == theLine.h ? anEqual.entityB : anEqual.entityA;
if (myStorage->isEntityFixed(anOtherEntID, true)) {
fixPoint(theCircle.point[0]);
if (isFixRadius) {
+ // Search the radius is already fixed
+ std::list<Slvs_Constraint> aDiamConstr = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
+ std::list<Slvs_Constraint>::const_iterator aDiamIter = aDiamConstr.begin();
+ for (; aDiamIter != aDiamConstr.end(); aDiamIter++)
+ if (aDiamIter->entityA == theCircle.h)
+ return;
+
// Fix radius of a circle
AttributeDoublePtr aRadiusAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
myFeatureMap.begin()->first->attribute(SketchPlugin_Circle::RADIUS_ID()));
std::list<Slvs_Constraint> aDiamConstraints = myStorage->getConstraintsByType(SLVS_C_DIAMETER);
std::list<Slvs_Constraint>::iterator anIt = aDiamConstraints.begin();
for (; anIt != aDiamConstraints.end() && !isExists; anIt++)
- if (anIt->entityA == myFeatureMap.begin()->second)
+ if (anIt->entityA == theArc.h)
isExists = true;
if (!isExists) {
Slvs_Constraint aFixedR = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(), SLVS_C_DIAMETER,
return false;
}
+bool SketchSolver_ConstraintRigid::isAxisParallel(const Slvs_Entity& theEntity) const
+{
+ std::list<Slvs_Constraint> aConstr = myStorage->getConstraintsByType(SLVS_C_HORIZONTAL);
+ std::list<Slvs_Constraint> aVert = myStorage->getConstraintsByType(SLVS_C_VERTICAL);
+ aConstr.insert(aConstr.end(), aVert.begin(), aVert.end());
+
+ std::list<Slvs_Constraint>::const_iterator anIter = aConstr.begin();
+ for (; anIter != aConstr.end(); anIter++)
+ if (anIter->entityA == theEntity.h)
+ return true;
+ return false;
+}
/// \return \c true, if the Equal constrait is found
bool isUsedInEqual(const Slvs_Entity& theEntity, Slvs_Constraint& theEqual) const;
+ /// \brief Check the entity is horizontal of vertical
+ bool isAxisParallel(const Slvs_Entity& theEntity) const;
+
protected:
FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
};
#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_ResultConstruction.h>
+#include <GeomDataAPI_Point2D.h>
void SketchSolver_FeatureStorage::changeConstraint(ConstraintPtr theConstraint)
{
return; // no such attribute
anAttrIter->second.erase(theFeature);
+ if (!anAttrIter->second.empty())
+ return;
+
+ // Check there is no features containing such attribute
+ MapFeatureConstraint::iterator aFeatIter = myFeatures.begin();
+ for (; aFeatIter != myFeatures.end(); aFeatIter++) {
+ DataPtr aData = aFeatIter->first->data();
+ if (!aData || !aData->isValid())
+ continue;
+ std::list<AttributePtr> anAttrList = aData->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator anAtIt = anAttrList.begin();
+ for (; anAtIt != anAttrList.end(); anAtIt++) {
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anAtIt);
+ if (aPoint == theAttribute)
+ anAttrIter->second.insert(aFeatIter->first);
+ }
+ }
if (anAttrIter->second.empty())
myAttributes.erase(anAttrIter);
}
if (!theConstraint)
return false;
- if (myConstraints.find(theConstraint) == myConstraints.end()) {
+ bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
+ if (isNewConstraint) {
// Add constraint to the current group
SolverConstraintPtr aConstraint =
SketchSolver_Builder::getInstance()->createConstraint(theConstraint);
myConstraints[theConstraint]->update();
// Fix base features for fillet
- if (theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
+ if (isNewConstraint && theConstraint->getKind() == SketchPlugin_ConstraintFillet::ID()) {
std::list<AttributePtr> anAttrList =
theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
std::list<AttributePtr>::iterator anAttrIter = anAttrList.begin();
int aResult = SLVS_RESULT_OKAY;
try {
- aResult = myConstrSolver.solve();
+ if (myStorage->hasDuplicatedConstraint())
+ aResult = SLVS_RESULT_INCONSISTENT;
+ else {
+ // To avoid overconstraint situation, we will remove temporary constraints one-by-one
+ // and try to find the case without overconstraint
+ int aNbTemp = (int)myTempConstraints.size();
+ while (true) {
+ aResult = myConstrSolver.solve();
+ if (aResult == SLVS_RESULT_OKAY || aNbTemp <= 0)
+ break;
+ aNbTemp = myStorage->removeFirstTemporaryConstraint();
+ myStorage->initializeSolver(myConstrSolver);
+ }
+ }
} catch (...) {
Events_Error::send(SketchSolver_Error::SOLVESPACE_CRASH(), this);
return false;
myEquationsSystem.constraints = theSize;
}
else if (myEquationsSystem.constraints != theSize) {
- delete[] myEquationsSystem.constraint;
- myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+ if (theSize > myEquationsSystem.constraints) {
+ delete[] myEquationsSystem.constraint;
+ myEquationsSystem.constraint = new Slvs_Constraint[theSize];
+ }
myEquationsSystem.constraints = theSize;
}
memcpy(myEquationsSystem.constraint, theConstraints, theSize * sizeof(Slvs_Constraint));
myEntityMaxID(SLVS_E_UNKNOWN),
myConstrMaxID(SLVS_C_UNKNOWN),
myFixed(SLVS_E_UNKNOWN),
- myNeedToResolve(false)
+ myNeedToResolve(false),
+ myDuplicatedConstraint(false)
{
}
return true;
}
}
- // 2. The line is used in Parallel/Perpendicular and Length constraints
+ // 2. The line is used in Parallel/Perpendicular/Vertical/Horizontal and Length constraints
aList = getConstraintsByType(SLVS_C_PARALLEL);
aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
+ aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
for (anIt = aList.begin(); anIt != aList.end(); anIt++)
if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
Slvs_Constraint aConstraint = theConstraint;
- // Find a constraint with same type uses same arguments
+ // Find a constraint with same type uses same arguments to show user overconstraint situation
std::vector<Slvs_Constraint>::iterator aCIt = myConstraints.begin();
for (; aCIt != myConstraints.end(); aCIt++) {
if (aConstraint.type != aCIt->type)
continue;
if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
- aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD) {
- aConstraint.h = aCIt->h;
- return updateConstraint(aConstraint);
- }
+ aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
+ myDuplicatedConstraint = true;
}
if (aConstraint.h > myConstrMaxID)
// remove temporary fixed point, if available
if (myFixed == theConstraintID)
myFixed = SLVS_E_UNKNOWN;
+ if (myDuplicatedConstraint) {
+ // Check the duplicated constraints are still available
+ myDuplicatedConstraint = false;
+ std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
+ std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
+ for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
+ for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
+ if (anIt1->type != anIt2->type)
+ continue;
+ if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
+ anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
+ anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
+ myDuplicatedConstraint = true;
+ }
+ }
}
return aResult;
}
myTemporaryConstraints.clear();
}
+int SketchSolver_Storage::removeFirstTemporaryConstraint()
+{
+ if (myTemporaryConstraints.empty())
+ return 0;
+ removeConstraint(*myTemporaryConstraints.begin());
+ myTemporaryConstraints.erase(myTemporaryConstraints.begin());
+ return (int)myTemporaryConstraints.size();
+}
+
bool SketchSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
{
return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
void addTemporaryConstraint(const Slvs_hConstraint& theConstraintID);
/// \brief Remove all transient constraints
void removeTemporaryConstraints();
+ /// \brief Remove first temporary constraint
+ /// \return Number of remaining temporary constraints
+ int removeFirstTemporaryConstraint();
/// \brief Checks the constraint is temporary
bool isTemporary(const Slvs_hConstraint& theConstraintID) const;
bool isNeedToResolve() const
{ return myNeedToResolve; }
+ /// \brief Shows the storage has the same constraint twice
+ bool hasDuplicatedConstraint() const
+ { return myDuplicatedConstraint; }
+
/// \brief Changes the flag of group to be resolved
void setNeedToResolve(bool theFlag)
{ myNeedToResolve = theFlag; }
Slvs_hConstraint myFixed; ///< identifier of one of temporary constraints to fix separate point
bool myNeedToResolve; ///< parameters are changed and group needs to be resolved
+ bool myDuplicatedConstraint; ///< shows the storage has same constraint twice
std::set<Slvs_hConstraint> myTemporaryConstraints; ///< list of transient constraints
std::set<Slvs_hParam> myRemovedParameters; ///< list of just removed parameters (cleared when returning to applicant)
//aFlyout = aDist;
//SetFlyout(aFlyout);
- SetFlyout(SketcherPrs_Tools::getFlyoutDistance(myConstraint, myPlane));
+ SetFlyout(SketcherPrs_Tools::getFlyoutDistance(myConstraint));
SetMeasuredGeometry(aPnt1, aPnt2, myPlane->impl<gp_Ax3>());
AIS_LengthDimension::Compute(thePresentationManager, thePresentation, theMode);
}
GeomAPI_Circ aCircle(aCenter, aNormal, aRadius);
- std::shared_ptr<GeomAPI_Pnt> anAnchor = aCircle.project(aFlyoutPnt);
- std::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
- anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
- std::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
- const double aDelta = 1e-3;
- anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
- anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
- anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
+ std::shared_ptr<GeomAPI_Pnt> anAnchor = SketcherPrs_Tools::getAnchorPoint(myConstraint, myPlane);
+ //std::shared_ptr<GeomAPI_Pnt> anAnchor = aCircle.project(aFlyoutPnt);
+ //std::shared_ptr<GeomAPI_XYZ> anAnchorXYZ = anAnchor->xyz();
+ //anAnchorXYZ = anAnchorXYZ->decreased(aCenter->xyz());
+ //std::shared_ptr<GeomAPI_Dir> aDeltaDir(new GeomAPI_Dir(anAnchorXYZ));
+ //const double aDelta = 1e-3;
+ //anAnchor->setX(anAnchor->x() + aDelta * aDeltaDir->x());
+ //anAnchor->setY(anAnchor->y() + aDelta * aDeltaDir->y());
+ //anAnchor->setZ(anAnchor->z() + aDelta * aDeltaDir->z());
SetMeasuredGeometry(aCircle.impl<gp_Circ>(), anAnchor->impl<gp_Pnt>());
SetCustomValue(aRadius);
#include <SketchPlugin_Point.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Arc.h>
#include <ModelAPI_ResultConstruction.h>
#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeDouble.h>
#include <GeomDataAPI_Point2D.h>
#include <GeomAPI_Lin2d.h>
MyArrowSize = theSize;
}
-double getFlyoutDistance(const ModelAPI_Feature* theConstraint,
- const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+double getFlyoutDistance(const ModelAPI_Feature* theConstraint)
{
std::shared_ptr<GeomDataAPI_Point2D> aFlyoutPoint =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
return aFlyoutPoint->y();
}
+std::shared_ptr<GeomAPI_Pnt> getAnchorPoint(const ModelAPI_Feature* theConstraint,
+ const std::shared_ptr<GeomAPI_Ax3>& thePlane)
+{
+ ModelAPI_Feature* aConstraint = const_cast<ModelAPI_Feature*>(theConstraint);
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aRefAttr || !aRefAttr->isObject() || !aRefAttr->object())
+ return std::shared_ptr<GeomAPI_Pnt>();
+
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter;
+ if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
+ aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+ } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
+ aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->attribute(SketchPlugin_Circle::CENTER_ID()))->pnt();
+ } else
+ return std::shared_ptr<GeomAPI_Pnt>();
+
+ std::shared_ptr<GeomAPI_Pnt2d> anOrigin(new GeomAPI_Pnt2d(0.0, 0.0));
+ std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()))->pnt();
+ double aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ aConstraint->attribute(SketchPlugin_Constraint::VALUE()))->value();
+ double aLen = aFlyoutPnt->distance(anOrigin);
+ aRadius *= 1.001; // a gap to make point much closer to the circle, but not lying on it
+ aFlyoutPnt->setX(aCenter->x() + aFlyoutPnt->x() * aRadius / aLen);
+ aFlyoutPnt->setY(aCenter->y() + aFlyoutPnt->y() * aRadius / aLen);
+ return thePlane->to3D(aFlyoutPnt->x(), aFlyoutPnt->y());
+}
};
SKETCHERPRS_EXPORT void setArrowSize(double theSize);
- SKETCHERPRS_EXPORT double getFlyoutDistance(const ModelAPI_Feature* theConstraint,
+ SKETCHERPRS_EXPORT double getFlyoutDistance(const ModelAPI_Feature* theConstraint);
+
+ SKETCHERPRS_EXPORT std::shared_ptr<GeomAPI_Pnt> getAnchorPoint(
+ const ModelAPI_Feature* theConstraint,
const std::shared_ptr<GeomAPI_Ax3>& thePlane);
};
if (!aShapePrs.IsNull()) {
std::shared_ptr<GeomAPI_Shape> aShapePtr = ModelAPI_Tools::shape(aResult);
if (aShapePtr.get()) {
- const TopoDS_Shape& aShape = aShapePrs->Shape();
- std::shared_ptr<GeomAPI_Shape> anAISShapePtr(new GeomAPI_Shape());
- anAISShapePtr->setImpl(new TopoDS_Shape(aShape));
- isEqualShapes = aShapePtr->isEqual(anAISShapePtr);
+ const TopoDS_Shape& aOldShape = aShapePrs->Shape();
+ isEqualShapes = aOldShape.IsEqual(aShapePtr->impl<TopoDS_Shape>());
}
}
}
void XGUI_ModuleConnector::setSelected(const QObjectPtrList& theFeatures)
{
XGUI_Displayer* aDisp = myWorkshop->displayer();
- aDisp->setSelected(theFeatures);
+ if (theFeatures.isEmpty()) {
+ myWorkshop->selector()->clearSelection();
+ } else {
+ aDisp->setSelected(theFeatures);
+ }
}
bool XGUI_ModuleConnector::canStartOperation(QString theId)
}
//**************************************************************
-/*QFeatureList XGUI_SelectionMgr::selectedFeatures() const
- {
- return myWorkshop->objectBrowser()->selectedFeatures();
- }
-
- //**************************************************************
- QModelIndexList XGUI_SelectionMgr::selectedIndexes() const
- {
- return myWorkshop->objectBrowser()->selectedIndexes();
- }
-
- //**************************************************************
- void XGUI_SelectionMgr::selectedAISObjects(AIS_ListOfInteractive& theList) const
- {
- Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
- theList.Clear();
- for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected())
- theList.Append(aContext->SelectedInteractive());
- }
-
- //**************************************************************
- void XGUI_SelectionMgr::selectedShapes(NCollection_List<TopoDS_Shape>& theList) const
- {
- theList.Clear();
- Handle(AIS_InteractiveContext) aContext = myWorkshop->viewer()->AISContext();
- for (aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected()) {
- TopoDS_Shape aShape = aContext->SelectedShape();
- if (!aShape.IsNull())
- theList.Append(aShape);
- }
- }*/
+void XGUI_SelectionMgr::clearSelection()
+{
+ QObjectPtrList aFeatures;
+ bool aBlocked = myWorkshop->objectBrowser()->blockSignals(true);
+ myWorkshop->objectBrowser()->setObjectsSelected(aFeatures);
+ myWorkshop->objectBrowser()->blockSignals(aBlocked);
+
+ XGUI_Displayer* aDisplayer = myWorkshop->displayer();
+ aDisplayer->setSelected(aFeatures);
+
+ emit selectionChanged();
+}
/// \param isUpdateViewer the parameter whether the viewer should be update immediatelly
void updateSelectedOwners(bool isUpdateViewer);
+ //! Clears selection in Viewer and object Browser
+ void clearSelection();
+
signals:
//! Emited when selection in a one of viewers was changed
void selectionChanged();
myObjectBrowser(0),
myDisplayer(0),
myUpdatePrefs(false),
- myPartActivating(false)
+ myPartActivating(false),
+ myIsLoadingData(false)
{
myMainWindow = mySalomeConnector ? 0 : new AppElements_MainWindow();
return;
}
QApplication::setOverrideCursor(Qt::WaitCursor);
+ myIsLoadingData = true;
aSession->load(myCurrentDir.toLatin1().constData());
myObjectBrowser->rebuildDataTree();
displayAllResults();
updateCommandStatus();
+ myIsLoadingData = false;
QApplication::restoreOverrideCursor();
}
myDisplayer->display(theObj, false);
if (aNb == 0)
viewer()->fitAll();
- } else
+ } else if (!(myIsLoadingData || myPartActivating))
myDisplayer->display(theObj, false);
return true;
// Flag to check that part document is in process of activating
bool myPartActivating;
+
+ /// The flag is true when we loading a document
+ bool myIsLoadingData;
};
#endif