ADD_SUBDIRECTORY (src/XAO)
ADD_SUBDIRECTORY (src/GeomAPI)
ADD_SUBDIRECTORY (src/ModelAPI)
+ADD_SUBDIRECTORY (src/ModelGeomAlgo)
ADD_SUBDIRECTORY (src/GeomAlgoAPI)
ADD_SUBDIRECTORY (src/GeomAlgoImpl)
ADD_SUBDIRECTORY (src/GeomData)
#include <TopoDS_Vertex.hxx>
#include <TopoDS.hxx>
#include <TopExp_Explorer.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+#include <BOPAlgo_Builder.hxx>
+#include <BRepBuilderAPI_MakeVertex.hxx>
+#include <TopoDS_Edge.hxx>
//==================================================================================================
double GeomAlgoAPI_ShapeTools::volume(const std::shared_ptr<GeomAPI_Shape> theShape)
BRepExtrema_ExtCF anExt(anEdge, aFace);
return anExt.IsParallel() == Standard_True;
}
+
+//==================================================================================================
+void GeomAlgoAPI_ShapeTools::splitShape(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
+ const std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+ std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes)
+{
+ // General Fuse to split edge by vertices
+ BOPAlgo_Builder aBOP;
+ const TopoDS_Edge& aBaseEdge = theBaseShape->impl<TopoDS_Edge>();
+ aBOP.AddArgument(aBaseEdge);
+
+ std::set<std::shared_ptr<GeomAPI_Pnt> >::const_iterator aPtIt = thePoints.begin();
+ for (; aPtIt != thePoints.end(); ++aPtIt) {
+ std::shared_ptr<GeomAPI_Pnt> aPnt = *aPtIt;
+ TopoDS_Vertex aV = BRepBuilderAPI_MakeVertex(gp_Pnt(aPnt->x(), aPnt->y(), aPnt->z()));
+ aBOP.AddArgument(aV);
+ }
+
+ aBOP.Perform();
+ if (aBOP.ErrorStatus())
+ return;
+
+ // Collect splits
+ const TopTools_ListOfShape& aSplits = aBOP.Modified(aBaseEdge);
+ TopTools_ListIteratorOfListOfShape anIt(aSplits);
+ for (; anIt.More(); anIt.Next()) {
+ std::shared_ptr<GeomAPI_Shape> anEdge(new GeomAPI_Shape);
+ anEdge->setImpl(new TopoDS_Shape(anIt.Value()));
+ theShapes.insert(anEdge);
+ }
+}
#include <GeomAPI_Shape.h>
#include <GeomAPI_Vertex.h>
+#include <set>
+
class GeomAPI_Edge;
class GeomAPI_Dir;
class GeomAPI_Face;
/// \return true if edge is parallel to face.
GEOMALGOAPI_EXPORT static bool isParallel(const std::shared_ptr<GeomAPI_Edge> theEdge,
const std::shared_ptr<GeomAPI_Face> theFace);
+ /// \brief Performs the split of the shape by points.
+ /// \param[in] theBaseShape shape that should be splitted.
+ /// \param[in] thePoints container of points to split
+ /// \param[out] theShapes container of shapes after split
+ GEOMALGOAPI_EXPORT static void splitShape(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
+ const std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
+ std::set<std::shared_ptr<GeomAPI_Shape> >& theShapes);
};
#endif
return theResult->shape();
}
+void shapesOfType(const FeaturePtr& theFeature,
+ const GeomAPI_Shape::ShapeType& theType,
+ std::set<GeomShapePtr>& theShapes)
+{
+ std::list<ResultPtr> aResults = theFeature->results();
+ std::list<ResultPtr>::const_iterator aRIter = aResults.cbegin();
+ for (; aRIter != aResults.cend(); aRIter++) {
+ ResultPtr aResult = *aRIter;
+ GeomShapePtr aShape = aResult->shape();
+ if (aShape.get() && aShape->shapeType() == theType)
+ theShapes.insert(aShape);
+ }
+}
+
const char* toString(ModelAPI_ExecState theExecState)
{
#define TO_STRING(__NAME__) case __NAME__: return #__NAME__;
/// Returns shape from the given Result object
MODELAPI_EXPORT std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult);
+/// Creates a container of shape of the feature results satisfied the given shape type
+/// \param theFeature a source feature
+/// \param theType shape type
+/// \param an output container for shapes
+MODELAPI_EXPORT void shapesOfType(const FeaturePtr& theFeature,
+ const GeomAPI_Shape::ShapeType& theType,
+ std::set<GeomShapePtr>& theShapes);
+
/*! Returns the feature error generated according to feature error and exec state
* \param theFeature a feature
* \return error value or empty string
--- /dev/null
+## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+FIND_PACKAGE(SWIG REQUIRED)
+INCLUDE(${SWIG_USE_FILE})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
+INCLUDE(UnitTest)
+
+SET(PROJECT_HEADERS
+ ModelGeomAlgo.h
+ ModelGeomAlgo_Point2D.h
+)
+
+SET(PROJECT_SOURCES
+ ModelGeomAlgo_Point2D.cpp
+)
+
+SET(PROJECT_LIBRARIES
+ Config
+ GeomAPI
+ GeomDataAPI
+ GeomAlgoAPI
+ ModelAPI
+)
+
+SET(CMAKE_SWIG_FLAGS -threads -Wall)
+ADD_DEFINITIONS(-DMODELGEOMALGO_EXPORTS)
+
+ADD_LIBRARY(ModelGeomAlgo SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS})
+SET_TARGET_PROPERTIES(ModelGeomAlgo PROPERTIES LINKER_LANGUAGE CXX)
+TARGET_LINK_LIBRARIES(ModelGeomAlgo ${PROJECT_LIBRARIES})
+
+INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Config
+ ${PROJECT_SOURCE_DIR}/src/Events
+ ${PROJECT_SOURCE_DIR}/src/GeomAPI
+ ${PROJECT_SOURCE_DIR}/src/GeomDataAPI
+ ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
+ ${PROJECT_SOURCE_DIR}/src/ModelAPI
+)
+
+
+SET_SOURCE_FILES_PROPERTIES(ModelGeomAlgo.i PROPERTIES CPLUSPLUS ON)
+# "-includeall" is not needed: it starts to follow the standard inludes (like "string") without success
+# SET_SOURCE_FILES_PROPERTIES(ModelGeomAlgo.i PROPERTIES SWIG_FLAGS)
+SET_SOURCE_FILES_PROPERTIES(ModelGeomAlgo.i PROPERTIES SWIG_DEFINITIONS "-shadow")
+#SET_SOURCE_FILES_PROPERTIES(ModelGeomAlgoPYTHON_wrap.cxx PROPERTIES COMPILE_FLAGS "-D_WIN32")
+
+SET(SWIG_SCRIPTS
+ ${CMAKE_CURRENT_BINARY_DIR}/ModelGeomAlgo.py
+)
+
+SET(SWIG_LINK_LIBRARIES
+ ModelGeomAlgo
+ GeomAPI
+ ${PYTHON_LIBRARIES}
+)
+
+SWIG_ADD_MODULE(ModelGeomAlgo python ModelGeomAlgo.i ${PROJECT_HEADERS})
+SWIG_LINK_LIBRARIES(ModelGeomAlgo ${SWIG_LINK_LIBRARIES})
+
+IF(WIN32)
+ SET_TARGET_PROPERTIES(_ModelGeomAlgo PROPERTIES DEBUG_OUTPUT_NAME _ModelGeomAlgo_d)
+ENDIF(WIN32)
+
+INSTALL(TARGETS _ModelGeomAlgo DESTINATION ${SHAPER_INSTALL_SWIG})
+INSTALL(TARGETS ModelGeomAlgo DESTINATION ${SHAPER_INSTALL_BIN})
+INSTALL(FILES ${SWIG_SCRIPTS} DESTINATION ${SHAPER_INSTALL_SWIG})
+
+ADD_UNIT_TESTS(TestPoint2D.py)
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#ifndef MODELGEOMALGO_H
+#define MODELGEOMALGO_H
+
+#if defined MODELGEOMALGO_EXPORTS
+#if defined WIN32
+#define MODELGEOMALGO_EXPORT __declspec( dllexport )
+#else
+#define MODELGEOMALGO_EXPORT
+#endif
+#else
+#if defined WIN32
+#define MODELGEOMALGO_EXPORT __declspec( dllimport )
+#else
+#define MODELGEOMALGO_EXPORT
+#endif
+#endif
+
+#endif
--- /dev/null
+/* ModelAPI.i */
+%module(directors="1") ModelGeomAlgo
+%feature("director:except") {
+ if ($error != NULL) {
+ PyErr_Print();
+ std::cerr << std::endl;
+ throw Swig::DirectorMethodException();
+ }
+}
+
+%{
+ #include "ModelGeomAlgo_swig.h"
+%}
+
+// import other modules
+%import "GeomAPI.i"
+%import "GeomDataAPI.i"
+%import "ModelAPI.i"
+
+
+// to avoid error on this
+#define MODELGEOMALGO_EXPORT
+
+// standard definitions
+%include "typemaps.i"
+%include "std_string.i"
+%include "std_list.i"
+%include "std_shared_ptr.i"
+%include "std_set.i"
+
+// shared pointers
+// For Point2D.method()
+%shared_ptr(ModelAPI_Point2D)
+
+// all supported interfaces
+%include "ModelGeomAlgo_Point2D.h"
+
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModelAPI_Tools.cpp
+// Created: 20 Jul 2016
+// Author: Natalia ERMOLAEVA
+
+#include "ModelGeomAlgo_Point2D.h"
+
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_AttributeRefAttr.h>
+
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <GeomAPI_Pnt.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_Vertex.h>
+#include <GeomAPI_Dir.h>
+
+namespace ModelGeomAlgo_Point2D {
+ std::shared_ptr<GeomDataAPI_Point2D> getPointOfRefAttr(ModelAPI_Feature* theFeature,
+ const std::string& theAttribute,
+ const std::string& theObjectFeatureKind,
+ const std::string& theObjectFeatureAttribute)
+ {
+ std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
+
+ /// essential check as it is called in openGl thread
+ if (!theFeature || !theFeature->data().get() || !theFeature->data()->isValid())
+ return std::shared_ptr<GeomDataAPI_Point2D>();
+
+ FeaturePtr aFeature;
+ std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
+ ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
+ if(!anAttr.get()) {
+ return std::shared_ptr<GeomDataAPI_Point2D>();
+ }
+ aFeature = ModelAPI_Feature::feature(anAttr->object());
+
+ bool aFeatureOfObjectKind = !theObjectFeatureKind.empty() &&
+ !theObjectFeatureAttribute.empty() &&
+ aFeature->getKind() == theObjectFeatureKind;
+ if (aFeature.get() && aFeatureOfObjectKind)
+ aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature->data()->attribute(theObjectFeatureAttribute));
+ else if (anAttr->attr())
+ aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
+
+ return aPointAttr;
+ }
+
+ void getPointsOfReference(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::string& theReferenceFeatureKind,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
+ const std::string& theObjectFeatureKind,
+ const std::string& theObjectFeatureAttribute)
+ {
+ const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aIt;
+ for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
+ std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
+ FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
+ if (aRefFeature->getKind() == theReferenceFeatureKind) {
+ std::list<AttributePtr> anAttributes =
+ theFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+ std::list<AttributePtr>::iterator anIter = anAttributes.begin();
+ // it searches the first point of AttributeRefAtt
+ std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
+ for(; anIter != anAttributes.end() && !aPointAttr.get(); anIter++) {
+ AttributeRefAttrPtr aRefAttribute =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
+ if (aRefAttribute.get())
+ aPointAttr = getPointOfRefAttr(aRefFeature.get(), aRefAttribute->id(),
+ theObjectFeatureKind, theObjectFeatureAttribute);
+ }
+ if (aPointAttr.get()) {
+ theAttributes.insert(aPointAttr);
+ }
+ }
+ }
+ }
+
+ void getPointsInsideShape(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+ const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
+ const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
+ const std::shared_ptr<GeomAPI_Dir>& theDirX,
+ const std::shared_ptr<GeomAPI_Dir>& theDirY,
+ std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints)
+ {
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
+ aLast = theAttributes.end();
+ for (; anIt != aLast; anIt++) {
+ std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
+ std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
+ std::shared_ptr<GeomAPI_Pnt> aPnt = aPnt2d->to3D(theOrigin, theDirX, theDirY);
+ std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(aPnt->x(), aPnt->y(), aPnt->z()));
+ if (GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertexShape, theBaseShape))
+ thePoints.insert(aPnt);
+ }
+ }
+
+
+} // namespace ModelGeomAlgo_Point2D
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModelGeomAlgo_Point2D.h
+// Created: 20 Jul 2016
+// Author: Natalia ERMOLAEVA
+
+#ifndef ModelGeomAlgo_Point2D_H
+#define ModelGeomAlgo_Point2D_H
+
+#include "ModelGeomAlgo.h"
+
+class ModelAPI_Feature;
+class GeomAPI_Shape;
+class GeomAPI_Pnt;
+class GeomAPI_Dir;
+
+class GeomDataAPI_Point2D;
+
+#include <memory>
+#include <set>
+
+
+namespace ModelGeomAlgo_Point2D {
+
+ /// Searches Point2D attribute of reference of the attribute of given feature
+ /// \param theFeature a feature to obtain AttributeRefAttr
+ /// \param theAttribute a name of AttributeRefAttr on the given feature
+ /// \param theObjectFeatureKind a feature kind in object of attribute that satisfies the search
+ /// \param theObjectFeatureAttribute a feature attribute in object that satisfies the search
+ /// \returns found point attribute or NULL
+ MODELGEOMALGO_EXPORT std::shared_ptr<GeomDataAPI_Point2D> getPointOfRefAttr(
+ ModelAPI_Feature* theFeature,
+ const std::string& theAttribute,
+ const std::string& theObjectFeatureKind = "",
+ const std::string& theObjectFeatureAttribute = "");
+
+ /// Fills container of point 2D attributes, which refer to the feature through the references
+ /// features with the given kind
+ /// \param theFeature a feature where references should be searched (e.g. a sketch line)
+ /// \param theReferenceFeatureKind a kind of the feature to be processed (e.g. coincidence constraint)
+ /// \param theAttributes a container of found point 2D attributes
+ /// \param theObjectFeatureKind a feature kind in object of attribute that satisfies the search
+ /// \param theObjectFeatureAttribute a feature attribute in object that satisfies the search
+ /// \returns found point attribute or NULL
+ MODELGEOMALGO_EXPORT void getPointsOfReference(const std::shared_ptr<ModelAPI_Feature>& theFeature,
+ const std::string& theReferenceFeatureKind,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
+ const std::string& theObjectFeatureKind = "",
+ const std::string& theObjectFeatureAttribute = "");
+
+ /// Removes attributes which points are out of the base shape
+ /// \param theBaseShape a shape of check
+ /// \param theAttributes a container of point 2D attributes
+ /// \param theOrigin origin of a plane to generate 3D point by 2D attribute point
+ /// \param theDirX plane X direction to generate 3D point by 2D attribute point
+ /// \param theDirY plane X direction to generate 3D point by 2D attribute point
+ /// \param thePoints a container of 3D points belong to the shape
+ MODELGEOMALGO_EXPORT void getPointsInsideShape(
+ const std::shared_ptr<GeomAPI_Shape> theBaseShape,
+ const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
+ const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
+ const std::shared_ptr<GeomAPI_Dir>& theDirX,
+ const std::shared_ptr<GeomAPI_Dir>& theDirY,
+ std::set<std::shared_ptr<GeomAPI_Pnt> >& thePoints);
+}
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: ModelAPI_swig.h
+// Created: Jul 20, 2016
+// Author: Natalia ERMOLAEVA
+
+#ifndef SRC_MODELGEOMALGO_MODELGEOMALGO_SWIG_H_
+#define SRC_MODELGEOMALGO_MODELGEOMALGO_SWIG_H_
+
+ #include <GeomAPI_swig.h>
+ #include <ModelAPI_swig.h>
+ #include <GeomDataAPI_swig.h>
+
+ #include "ModelGeomAlgo.h"
+ #include "ModelGeomAlgo_Point2D.h"
+
+ #include <memory>
+ #include <string>
+
+#endif /* SRC_MODELGEOMALGO_MODELGEOMALGO_SWIG_H_ */
--- /dev/null
+"""
+ TestPoint2D.py
+ Unit test for testing the Point2D algorithms
+
+"""
+#=========================================================================
+# Initialization of the test
+#=========================================================================
+from ModelAPI import *
+from GeomDataAPI import *
+from GeomAlgoAPI import *
+from GeomAPI import *
+from ModelGeomAlgo import *
+
+__updated__ = "2016-07-20"
+
+aSession = ModelAPI_Session.get()
}
-void ModuleBase_IModule::launchOperation(const QString& theCmdId,
- const bool isUpdatePropertyPanel)
+void ModuleBase_IModule::launchOperation(const QString& theCmdId)
{
if (!myWorkshop->canStartOperation(theCmdId))
return;
ModuleBase_ISelection* aSelection = myWorkshop->selection();
// Initialise operation with preliminary selection
aFOperation->initSelection(aSelection, myWorkshop->viewer());
- sendOperation(aFOperation, isUpdatePropertyPanel);
+ workshop()->processLaunchOperation(aFOperation);
}
}
-
-void ModuleBase_IModule::sendOperation(ModuleBase_Operation* theOperation,
- const bool isUpdatePropertyPanel)
-{
- workshop()->processLaunchOperation(theOperation, isUpdatePropertyPanel);
-}
-
Handle(AIS_InteractiveObject) ModuleBase_IModule::createPresentation(const ResultPtr& theResult)
{
return Handle(AIS_InteractiveObject)();
(createOperation(aFeatureId));
if (aFOperation) {
aFOperation->setFeature(theFeature);
- sendOperation(aFOperation);
+ workshop()->processLaunchOperation(aFOperation);
}
}
\r
/// Creates an operation and send it to loop\r
/// \param theCmdId the operation name\r
- /// \param isUpdatePropertyPanel if false, the property panel filling might be postponed\r
- virtual void launchOperation(const QString& theCmdId, const bool isUpdatePropertyPanel = true);\r
+ virtual void launchOperation(const QString& theCmdId);\r
\r
/// Executes feature as a modal dialog box\r
/// \param theCmdId the operation name\r
/// \param theCmdId the operation name\r
virtual ModuleBase_Operation* createOperation(const std::string& theCmdId);\r
\r
- /// Sends the operation for launching\r
- /// \param theOperation the operation\r
- /// \param isUpdatePropertyPanel if false, the property panel filling might be postponed\r
- virtual void sendOperation(ModuleBase_Operation* theOperation, const bool isUpdatePropertyPanel = true);\r
-\r
/// Create specific for the module presentation\r
/// \param theResult an object for presentation\r
/// \return created presentation or NULL(default value)\r
/// \param thePreviousAttributeID an index of the previous active attribute\r
virtual bool processEnter(const std::string& thePreviousAttributeID) { return false; };\r
\r
- /// Performs some GUI actions after an operation transaction is opened\r
- /// Default realization is empty\r
- virtual void beforeOperationStarted(ModuleBase_Operation* theOperation) {};\r
-\r
/// Performs some GUI actions before an operation transaction is stopped\r
/// Default realization is empty\r
virtual void beforeOperationStopped(ModuleBase_Operation* theOperation) {};\r
//! Performs the operation launch
//! \param theOperation an operation to be launched
- virtual void processLaunchOperation(ModuleBase_Operation* theOperation, const bool isUpdatePropertyPanel) = 0;
+ virtual void processLaunchOperation(ModuleBase_Operation* theOperation) = 0;
//! Returns started operation by the operation identifier
//! \param theId an operation id
/// after debug, it may be corrected
myFlushUpdateBlocked = !isUpdateFlushed;
myFeature = theFeature;
- if (theToStoreValue)
- storeValue();
+ if (theToStoreValue) {
+ /// it is possible that the attribute is filled before the operation is started,
+ /// e.g. by reentrant operation case some attributes are filled by values of
+ /// feature of previous operation, we should not lost them here
+ if (!theFeature->data()->attribute(attributeID())->isInitialized())
+ storeValue();
+ }
myFlushUpdateBlocked = false;
}
#include <sstream>
#include <string>
+#ifdef WIN32
+#pragma warning(disable : 4996) // for getenv
+#endif
+
const double tolerance = 1e-7;
const double DEFAULT_DEVIATION_COEFFICIENT = 1.e-4;
PartSet_CustomPrs.h
PartSet_ExternalObjectsMgr.h
PartSet_Module.h
+ PartSet_MouseProcessor.h
PartSet_OperationPrs.h
PartSet_OverconstraintListener.h
PartSet_PreviewPlanes.h
PartSet_WidgetSketchCreator.h
PartSet_IconFactory.h
PartSet_WidgetChoice.h
+ PartSet_WidgetSubShapeSelector.h
)
SET(PROJECT_SOURCES
PartSet_MenuMgr.cpp
PartSet_WidgetSketchCreator.cpp
PartSet_IconFactory.cpp
+ PartSet_WidgetSubShapeSelector.cpp
)
SET(PROJECT_RESOURCES
SET(PROJECT_LIBRARIES
ModuleBase
+ ModelGeomAlgo
Config
GeomAPI
GeomDataAPI
- SketcherPrs
+ SketcherPrs
${QT_LIBRARIES}
${CAS_KERNEL}
${CAS_SHAPE}
${PROJECT_SOURCE_DIR}/src/Events
${PROJECT_SOURCE_DIR}/src/ModuleBase
${PROJECT_SOURCE_DIR}/src/ModelAPI
+ ${PROJECT_SOURCE_DIR}/src/ModelGeomAlgo
${PROJECT_SOURCE_DIR}/src/GeomDataAPI
${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI
${PROJECT_SOURCE_DIR}/src/SketchPlugin
void PartSet_Module::operationStarted(ModuleBase_Operation* theOperation)
{
- ModuleBase_IWorkshop* anIWorkshop = workshop();
- if (!theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel
- anIWorkshop->updateCommandStatus();
- }
- else {
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (theOperation);
- if (aFOperation) {
- XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(anIWorkshop);
- XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
- ModuleBase_ModelWidget* aFilledWidget = 0;
- bool aPostonedWidgetActivation = false;
- FeaturePtr aFeature = aFOperation->feature();
-
- std::string aGreedAttributeId = ModuleBase_Tools::findGreedAttribute(anIWorkshop, aFeature);
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (theOperation);
+ if (aFOperation) {
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(workshop());
+ XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
+
+ ModuleBase_ModelWidget* aFilledWidget = 0;
+ bool aPostonedWidgetActivation = false;
+
+ FeaturePtr aFeature = aFOperation->feature();
+ /// Restart sketcher operations automatically
+ /// it is important to call method of sketch reentrant manager before filling of PP
+ /// because it fills some created feature attributes, these new values should be used
+ /// to fill the property panel
+ mySketchReentrantMgr->operationStarted(theOperation);
+
+ aWorkshop->fillPropertyPanel(aFOperation);
+ // filling the operation values by the current selection
+ // if the operation can be committed after the controls filling, the method perform should
+ // be stopped. Otherwise unnecessary presentations can be shown(e.g. operation prs in sketch)
+ bool isOperationCommitted = false;
+ if (!aFOperation->isEditOperation()) {
+ std::string aGreedAttributeId = ModuleBase_Tools::findGreedAttribute(workshop(), aFeature);
// if there is a greed attribute, automatic commit by preselection for this feature is prohibited
- aWorkshop->setPropertyPanel(aFOperation);
-
- // filling the operation values by the current selection
- // if the operation can be committed after the controls filling, the method perform should
- // be stopped. Otherwise unnecessary presentations can be shown(e.g. operation prs in sketch)
- bool isOperationCommitted = false;
- if (!aFOperation->isEditOperation()) {
- aFilledWidget = aFOperation->activateByPreselection(aGreedAttributeId);
- if (currentOperation() != aFOperation)
- isOperationCommitted = true;
- else {
- if (aGreedAttributeId.empty()) {
- // a signal should be emitted before the next widget activation
- // because, the activation of the next widget will give a focus to the widget. As a result
- // the value of the widget is initialized. And commit may happens until the value is entered.
- if (aFilledWidget) {
- if (mySketchReentrantMgr->canBeCommittedByPreselection())
- isOperationCommitted = mySketchMgr->operationActivatedByPreselection();
- // activate the next obligatory widget
- if (!isOperationCommitted)
- aPropertyPanel->activateNextWidget(aFilledWidget);
- }
+ aFilledWidget = aFOperation->activateByPreselection(aGreedAttributeId);
+ if (currentOperation() != aFOperation)
+ isOperationCommitted = true;
+ else {
+ if (aGreedAttributeId.empty()) {
+ // a signal should be emitted before the next widget activation
+ // because, the activation of the next widget will give a focus to the widget. As a result
+ // the value of the widget is initialized. And commit may happens until the value is entered.
+ if (aFilledWidget) {
+ if (mySketchReentrantMgr->canBeCommittedByPreselection())
+ isOperationCommitted = mySketchMgr->operationActivatedByPreselection();
+ // activate the next obligatory widget
+ if (!isOperationCommitted)
+ aPropertyPanel->activateNextWidget(aFilledWidget);
}
- else { // there is a greed widget
- const QList<ModuleBase_ModelWidget*>& aWidgets = aPropertyPanel->modelWidgets();
- std::string aFirstAttributeId = aWidgets.front()->attributeID();
- // activate next widget after greeded if it is the first widget in the panel
- // else the first panel widget is already activated by operation start
- if (aFirstAttributeId == aGreedAttributeId)
- aPostonedWidgetActivation = true;
- }
- }
- } if (!isOperationCommitted) {
- anIWorkshop->updateCommandStatus();
- aWorkshop->connectToPropertyPanel(true);
- operationStartedInternal(aFOperation);
-
- // the objects of the current operation should be deactivated
- QObjectPtrList anObjects;
- anObjects.append(aFeature);
- std::list<ResultPtr> aResults;
- ModelAPI_Tools::allResults(aFeature, aResults);
- std::list<ResultPtr>::const_iterator aIt;
- for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
- anObjects.append(*aIt);
}
- QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
- for (; anIt != aLast; anIt++)
- aWorkshop->deactivateActiveObject(*anIt, false);
- if (anObjects.size() > 0) {
- XGUI_Displayer* aDisplayer = aWorkshop->displayer();
- aDisplayer->updateViewer();
+ else { // there is a greed widget
+ const QList<ModuleBase_ModelWidget*>& aWidgets = aPropertyPanel->modelWidgets();
+ std::string aFirstAttributeId = aWidgets.front()->attributeID();
+ // activate next widget after greeded if it is the first widget in the panel
+ // else the first panel widget is already activated by operation start
+ if (aFirstAttributeId == aGreedAttributeId)
+ aPostonedWidgetActivation = true;
}
}
- if (aPostonedWidgetActivation) {
- // if the widget is an empty in the chain of activated widgets, the current operation
- // is restarted. It should be performed after functionality of the operation starting
- aPropertyPanel->activateNextWidget(aFilledWidget);
+ } if (!isOperationCommitted) {
+ workshop()->updateCommandStatus();
+ aWorkshop->connectToPropertyPanel(true);
+ updateSketcherOnStart(aFOperation);
+ updatePresentationsOnStart(aFOperation);
+
+ // the objects of the current operation should be deactivated
+ QObjectPtrList anObjects;
+ anObjects.append(aFeature);
+ std::list<ResultPtr> aResults;
+ ModelAPI_Tools::allResults(aFeature, aResults);
+ std::list<ResultPtr>::const_iterator aIt;
+ for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
+ anObjects.append(*aIt);
}
+ QObjectPtrList::const_iterator anIt = anObjects.begin(), aLast = anObjects.end();
+ for (; anIt != aLast; anIt++)
+ aWorkshop->deactivateActiveObject(*anIt, false);
+ if (anObjects.size() > 0) {
+ XGUI_Displayer* aDisplayer = aWorkshop->displayer();
+ aDisplayer->updateViewer();
+ }
+ }
+ if (aPostonedWidgetActivation) {
+ // if the widget is an empty in the chain of activated widgets, the current operation
+ // is restarted. It should be performed after functionality of the operation starting
+ aPropertyPanel->activateNextWidget(aFilledWidget);
}
}
}
-void PartSet_Module::operationStartedInternal(ModuleBase_Operation* theOperation)
+void PartSet_Module::updateSketcherOnStart(ModuleBase_Operation* theOperation)
{
- /// Restart sketcher operations automatically
- mySketchReentrantMgr->operationStarted(theOperation);
-
if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
mySketchMgr->startSketch(theOperation);
}
else if (PartSet_SketcherMgr::isNestedSketchOperation(theOperation)) {
mySketchMgr->startNestedSketch(theOperation);
}
+}
+void PartSet_Module::updatePresentationsOnStart(ModuleBase_Operation* theOperation)
+{
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
if (aFOperation) {
myCustomPrs->activate(aFOperation->feature(), ModuleBase_IModule::CustomizeArguments, true);
return true;
}
-void PartSet_Module::launchOperation(const QString& theCmdId,
- const bool isUpdatePropertyPanel)
+void PartSet_Module::launchOperation(const QString& theCmdId)
{
myIsOperationIsLaunched = true;
storeConstraintsState(theCmdId.toStdString());
updateConstraintsState(theCmdId.toStdString());
- ModuleBase_IModule::launchOperation(theCmdId, isUpdatePropertyPanel);
+ ModuleBase_IModule::launchOperation(theCmdId);
myIsOperationIsLaunched = false;
}
return mySketchReentrantMgr->processEnter(thePreviousAttributeID);
}
-//******************************************************
-void PartSet_Module::beforeOperationStarted(ModuleBase_Operation* theOperation)
-{
-}
-
//******************************************************
void PartSet_Module::beforeOperationStopped(ModuleBase_Operation* theOperation)
{
/// Creates an operation and send it to loop
/// \param theCmdId the operation name
- /// \param isUpdatePropertyPanel if false, the property panel filling might be postponed
- virtual void launchOperation(const QString& theCmdId, const bool isUpdatePropertyPanel = true);
+ virtual void launchOperation(const QString& theCmdId);
/// Realizes some functionality by an operation start
/// Displays all sketcher sub-Objects, hides sketcher result, appends selection filters
/// \param thePreviousAttributeID an index of the previous active attribute
virtual bool processEnter(const std::string& thePreviousAttributeID);
- /// Performs some GUI actions after an operation transaction is opened
- /// Default realization is empty
- virtual void beforeOperationStarted(ModuleBase_Operation* theOperation);
-
/// Performs some GUI actions before an operation transaction is stopped
/// Default realization is empty
virtual void beforeOperationStopped(ModuleBase_Operation* theOperation);
/// \param isToConnect a boolean value whether connect or disconnect
virtual void connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect);
- /// Realizes some functionality by an operation start
- /// Displays all sketcher sub-Objects, hides sketcher result, appends selection filters
- /// Activate the operation presentation
- /// \param theOperation a started operation
- virtual void operationStartedInternal(ModuleBase_Operation* theOperation);
+ /// Updates reentrant manager state or sketcher operations for the started operation
+ /// \param theOperation the started operation
+ void updateSketcherOnStart(ModuleBase_Operation* theOperation);
+
+ /// Updates presetnations of results and arguments by operation start
+ /// \param theOperation the started operation
+ void updatePresentationsOnStart(ModuleBase_Operation* theOperation);
private slots:
void onTreeViewDoubleClick(const QModelIndex&);
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PartSet_MouseProcessor.hxx
+// Created: 21 Jul 2016
+// Author: Natalia ERMOLAEVA
+
+#ifndef PartSet_MouseProcessor_H
+#define PartSet_MouseProcessor_H
+
+#include "PartSet.h"
+
+class ModuleBase_IViewWindow;
+class QMouseEvent;
+
+/**
+ * This is an interface to allow processing of mouse events. Implementation of necessary methods
+* should be done in a child.
+*/
+class PartSet_MouseProcessor
+{
+public:
+ /// Processing the mouse move event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ PARTSET_EXPORT virtual void mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent) {}
+ /// Processing the mouse press event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ PARTSET_EXPORT virtual void mousePressed(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent) {}
+ /// Processing the mouse release event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ PARTSET_EXPORT virtual void mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent) {}
+ /// Processing the mouse double click event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ PARTSET_EXPORT virtual void mouseDoubleClick(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent) {}
+};
+
+#endif
#include "PartSet_SketcherMgr.h"
#include "PartSet_SketcherReetntrantMgr.h"
#include "PartSet_Module.h"
-#include "PartSet_WidgetPoint2d.h"
-#include "PartSet_WidgetPoint2dDistance.h"
+#include "PartSet_MouseProcessor.h"
#include "PartSet_Tools.h"
#include "PartSet_WidgetSketchLabel.h"
#include "PartSet_WidgetEditor.h"
aWorkshop->viewer()->enableDrawMode(myPreviousDrawModeEnabled);
myIsDragging = false;
+
+ ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
+ PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+ if (aProcessor)
+ aProcessor->mouseReleased(theWnd, theEvent);
}
void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
return;
- if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) {
- myIsMouseOverViewProcessed = true;
+ if (isNestedCreateOperation(getCurrentOperation())) {
// 1. perform the widget mouse move functionality and display the presentation
// the mouse move should be processed in the widget, if it can in order to visualize correct
// presentation. These widgets correct the feature attribute according to the mouse position
ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
- PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(anActiveWidget);
- if (aPoint2DWdg) {
- aPoint2DWdg->onMouseMove(theWnd, theEvent);
- }
- PartSet_WidgetPoint2dDistance* aDistanceWdg = dynamic_cast<PartSet_WidgetPoint2dDistance*>
- (anActiveWidget);
- if (aDistanceWdg) {
- aDistanceWdg->onMouseMove(theWnd, theEvent);
- }
- // the feature is to be erased here, but it is correct to call canDisplayObject because
- // there can be additional check (e.g. editor widget in distance constraint)
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
- (getCurrentOperation());
- if (aFOperation) {
- FeaturePtr aFeature = aFOperation->feature();
- visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
+ PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+ if (aProcessor)
+ aProcessor->mouseMoved(theWnd, theEvent);
+ if (!myIsMouseOverViewProcessed) {
+ myIsMouseOverViewProcessed = true;
+
+ // the feature is to be erased here, but it is correct to call canDisplayObject because
+ // there can be additional check (e.g. editor widget in distance constraint)
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (getCurrentOperation());
+ if (aFOperation) {
+ FeaturePtr aFeature = aFOperation->feature();
+ visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature));
+ }
}
}
-
//myClickedPoint.clear();
if (myIsDragging) {
/// improvement to deselect automatically all eventual selected objects, when
// returning to the neutral point of the Sketcher
// if the operation is restarted, the previous selection is used to initialize started operation
- if (myModule->isSketchNeutralPointActivated())
+ if (!myModule->sketchReentranceMgr()->isInternalEditStarted())
workshop()->selector()->clearSelection();
}
bool aSwitchedOn = true;
const QStringList& aConstrIds = constraintsIdList();
- const QStringList& aReplicationIds = replicationsIdList();
std::string aKind = theFeature->getKind();
- if (aConstrIds.contains(aKind.c_str()) ||
- aReplicationIds.contains(aKind.c_str())) {
+ if (aConstrIds.contains(QString(aKind.c_str()))) {
bool isTypedConstraint = false;
switch (theState) {
if (!isActiveMgr())
return;
+ if (myPreviousFeature.get() && myRestartingMode == RM_LastFeatureUsed) {
+ ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast<ModuleBase_OperationFeature*>(
+ myWorkshop->currentOperation());
+ CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+ copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch);
+ }
resetFlags();
}
ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel();
bool aWidgetIsFilled = false;
- //bool aCanBeActivatedByMove = false;
FeaturePtr aCurrentFeature = aFOperation->feature();
bool isLineFeature = false, isArcFeature = false;
if (aCurrentFeature->getKind() == SketchPlugin_Line::ID())
bool aCanBeActivatedByMove = isLineFeature || isArcFeature;
if (aCanBeActivatedByMove) {
+ myPreviousFeature = aFOperation->feature();
restartOperation();
+ myPreviousFeature = FeaturePtr();
anActiveWidget = module()->activeWidget();
aCurrentFeature = anActiveWidget->feature();
aProcessed = true;
- if (isLineFeature) {
- PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(anActiveWidget);
- if (aPoint2DWdg) { // line, start point should be equal last point of the last feature line
- QList<ModuleBase_ViewerPrsPtr> aSelection;
- aSelection.append(std::shared_ptr<ModuleBase_ViewerPrs>(
- new ModuleBase_ViewerPrs(aLastFeature, GeomShapePtr(), NULL)));
- aWidgetIsFilled = aPoint2DWdg->setSelection(aSelection, true);
- }
- }
- else if (isArcFeature) { // arc, start point should be equal last point of the last feature arc
- if (aCurrentFeature->getKind() == SketchPlugin_Arc::ID()) {
- // get the last point of the previuos arc feature(geom point 2d)
- std::shared_ptr<ModelAPI_Data> aData = aLastFeature->data();
- std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aData->attribute(SketchPlugin_Arc::END_ID()));
- // get point attribute on the current feature
- AttributeRefAttrPtr aTangentPointAttr = aCurrentFeature->data()->refattr(
- SketchPlugin_Arc::TANGENT_POINT_ID());
- aTangentPointAttr->setAttr(aPointAttr);
- aWidgetIsFilled = true;
- }
- }
+ if (isLineFeature || isArcFeature)
+ aWidgetIsFilled = true;
}
if (aWidgetIsFilled)
aPanel->activateNextWidget(anActiveWidget);
// onMouseRelease happens, which correct the point position
ModuleBase_Tools::blockUpdateViewer(true);
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (myWorkshop->currentOperation());
+ myPreviousFeature = aFOperation->feature();
restartOperation();
+ myPreviousFeature = FeaturePtr();
aProcessed = true;
// fill the first widget by the mouse event point
PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
ModuleBase_ModelWidget* aFirstWidget = aPanel->findFirstAcceptingValueWidget();
if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) {
- aPoint2DWdg->onMouseRelease(theWnd, theEvent);
+ aPoint2DWdg->mouseReleased(theWnd, theEvent);
}
// unblock viewer update
ModuleBase_Tools::blockUpdateViewer(false);
myIsFlagsBlocked = true;
FeaturePtr aPrevFeature = aFOperation->feature();
aFOperation->commit();
- module()->launchOperation(aFOperation->id(), false);
- // allow the same attribute values in restarted operation
- ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast<ModuleBase_OperationFeature*>(
- myWorkshop->currentOperation());
- copyReetntrantAttributes(aPrevFeature, aCurrentOperation->feature());
-
- // update property panel: it should be done because in launchOperation, the 'false' is given
- workshop()->propertyPanel()->updateContentWidget(aCurrentOperation->feature());
- workshop()->propertyPanel()->createContentPanel(aCurrentOperation->feature());
-
+ module()->launchOperation(aFOperation->id());
myIsFlagsBlocked = false;
resetFlags();
// we should avoid processing of the signal about no more widgets attributes and
CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
myInternalFeature = aSketch->addFeature(anOperationFeature->getKind());
- bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature);
+ bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature,
+ aSketch, false);
XGUI_PropertyPanel* aPropertyPanel = dynamic_cast<XGUI_PropertyPanel*>
(aFOperation->propertyPanel());
QObjectPtrList anObjects;
anObjects.append(myInternalFeature);
workshop()->deleteFeatures(anObjects);
+ myInternalFeature = FeaturePtr();
}
void PartSet_SketcherReetntrantMgr::resetFlags()
}
bool PartSet_SketcherReetntrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
- const FeaturePtr& theNewFeature)
+ const FeaturePtr& theNewFeature,
+ const CompositeFeaturePtr& theSketch,
+ const bool isTemporary)
{
bool aChanged = false;
- std::string aTypeAttributeId;
- if (theSourceFeature->getKind() == SketchPlugin_Circle::ID()) {
- aTypeAttributeId = SketchPlugin_Circle::CIRCLE_TYPE();
+ if (!theSourceFeature.get())
+ return aChanged;
+
+ std::string aFeatureKind = theSourceFeature->getKind();
+ if (aFeatureKind == SketchPlugin_Line::ID()) {
+ // Initialize new line with first point equal to end of previous
+ std::shared_ptr<ModelAPI_Data> aSFData = theSourceFeature->data();
+ std::shared_ptr<GeomDataAPI_Point2D> aSPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aSFData->attribute(SketchPlugin_Line::END_ID()));
+ std::shared_ptr<ModelAPI_Data> aNFData = theNewFeature->data();
+ std::shared_ptr<GeomDataAPI_Point2D> aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aNFData->attribute(SketchPlugin_Line::START_ID()));
+ aNPoint->setValue(aSPoint->x(), aSPoint->y());
+ PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint);
+
+ aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aSFData->attribute(SketchPlugin_Line::END_ID()));
+ aNPoint->setValue(aSPoint->x(), aSPoint->y());
}
- if (theSourceFeature->getKind() == SketchPlugin_Arc::ID()) {
- aTypeAttributeId = SketchPlugin_Arc::ARC_TYPE();
+ else if (aFeatureKind == SketchPlugin_Circle::ID()) {
+ // set circle type
+ std::string aTypeAttributeId = SketchPlugin_Circle::CIRCLE_TYPE();
+ AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
+ AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
+ aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
+ //ModuleBase_Tools::flushUpdated(theNewFeature);
+ aChanged = true;
}
- if (!aTypeAttributeId.empty()) {
+ else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+ // set arc type
+ std::string aTypeAttributeId = SketchPlugin_Arc::ARC_TYPE();
AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
- ModuleBase_Tools::flushUpdated(theNewFeature);
+
+ // if the arc is tangent, set coincidence to end point of the previous arc
+ std::string anArcType = aSourceFeatureTypeAttr->value();
+ if (anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT()) {
+ // get the last point of the previuos arc feature(geom point 2d)
+ std::shared_ptr<ModelAPI_Data> aSData = theSourceFeature->data();
+ std::shared_ptr<GeomDataAPI_Point2D> aSPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aSData->attribute(SketchPlugin_Arc::END_ID()));
+ // get point attribute on the current feature
+ AttributeRefAttrPtr aTangentPointAttr = theNewFeature->data()->refattr(
+ SketchPlugin_Arc::TANGENT_POINT_ID());
+ aTangentPointAttr->setAttr(aSPointAttr);
+
+ std::shared_ptr<GeomDataAPI_Point2D> aNPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theNewFeature->data()->attribute(SketchPlugin_Arc::END_ID()));
+ aNPointAttr->setValue(aSPointAttr->x(), aSPointAttr->y());
+
+ }
+ //ModuleBase_Tools::flushUpdated(theNewFeature);
aChanged = true;
}
return aChanged;
class ModuleBase_ModelWidget;
class ModuleBase_IViewWindow;
+class ModelAPI_CompositeFeature;
+
class QMouseEvent;
class XGUI_Workshop;
/// This is type for Circle and Arc features
/// \param theSourceFeature a source feature
/// \param theNewFeature a new feature
+ /// \param theSketch an active sketch
+ /// \param isTemporary is used to do not create additional features(e.g. coicidence for line)
/// \return true is something is copied
static bool copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
- const FeaturePtr& theNewFeature);
+ const FeaturePtr& theNewFeature,
+ const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
+ const bool isTemporary = false);
static bool isTangentArc(ModuleBase_Operation* theOperation);
bool myIsFlagsBlocked; /// true when reset of flags should not be perfromed
bool myIsInternalEditOperation; /// true when the 'internal' edit is started
+ FeaturePtr myPreviousFeature; /// feature of the previous operation, which is restarted
FeaturePtr myInternalFeature;
QWidget* myInternalWidget;
ModuleBase_ModelWidget* myInternalActiveWidget;
PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aX, aY);
}
}
- else if (canBeActivatedByMove()) {
- if (feature()->getKind() == SketchPlugin_Line::ID()) {
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aValue->object());
- // Initialize new line with first point equal to end of previous
- if (aFeature.get()) {
- std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
- std::shared_ptr<GeomDataAPI_Point2D> aPoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aData->attribute(SketchPlugin_Line::END_ID()));
- if (aPoint) {
- setPoint(aPoint->x(), aPoint->y());
- PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aPoint->x(),
- aPoint->y());
- isDone = true;
- }
- }
- }
- }
return isDone;
}
void PartSet_WidgetPoint2D::activateCustom()
{
- ModuleBase_IViewer* aViewer = myWorkshop->viewer();
- connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*)));
- connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)));
-
QIntList aModes;
aModes << TopAbs_VERTEX;
aModes << TopAbs_EDGE;
}
}
-bool PartSet_WidgetPoint2D::canBeActivatedByMove()
-{
- bool aCanBeActivated = false;
- if (feature()->getKind() == SketchPlugin_Line::ID() &&
- attributeID() == SketchPlugin_Line::START_ID())
- aCanBeActivated = true;
-
- return aCanBeActivated;
-}
-
void PartSet_WidgetPoint2D::deactivate()
{
// the value of the control should be stored to model if it was not
storeValue();
ModuleBase_ModelWidget::deactivate();
- ModuleBase_IViewer* aViewer = myWorkshop->viewer();
- disconnect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*)));
- disconnect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)));
-
myWorkshop->deactivateSubShapesSelection();
}
return true;
}
-void PartSet_WidgetPoint2D::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
+void PartSet_WidgetPoint2D::mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent)
{
// the contex menu release by the right button should not be processed by this widget
if (theEvent->button() != Qt::LeftButton)
return;
ModuleBase_ISelection* aSelection = myWorkshop->selection();
- Handle(V3d_View) aView = theWnd->v3dView();
+ Handle(V3d_View) aView = theWindow->v3dView();
QList<ModuleBase_ViewerPrsPtr> aList = aSelection->getSelected(ModuleBase_ISelection::Viewer);
ModuleBase_ViewerPrsPtr aFirstValue = aList.size() > 0 ? aList.first() : ModuleBase_ViewerPrsPtr();
}
else if (aShape.ShapeType() == TopAbs_EDGE) {
if (!setConstraintWith(aObject)) {
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView());
+ gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, aY);
setPoint(aX, aY);
}
// End of Bug dependent fragment
else {
// A case when point is taken from mouse event
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView());
+ gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
double aX, anY;
PartSet_Tools::convertTo2D(aPoint, mySketch, aView, aX, anY);
}
-void PartSet_WidgetPoint2D::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
+void PartSet_WidgetPoint2D::mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent)
{
if (isEditingMode())
return;
- gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWnd->v3dView());
+ gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
double aX, anY;
- PartSet_Tools::convertTo2D(aPoint, mySketch, theWnd->v3dView(), aX, anY);
+ PartSet_Tools::convertTo2D(aPoint, mySketch, theWindow->v3dView(), aX, anY);
if (myState != ModifiedInViewer)
storeCurentValue();
// we need to block the value state change
#define PartSet_WidgetPoint2D_H
#include "PartSet.h"
+#include "PartSet_MouseProcessor.h"
+
#include <ModelAPI_CompositeFeature.h>
#include <ModuleBase_ModelWidget.h>
* <sketch-2dpoint_selector id="CircleCenter" title="Center" tooltip="Center coordinates"/>
* \endcode
*/
-class PARTSET_EXPORT PartSet_WidgetPoint2D : public ModuleBase_ModelWidget
+class PARTSET_EXPORT PartSet_WidgetPoint2D : public ModuleBase_ModelWidget,
+ public PartSet_MouseProcessor
{
Q_OBJECT
public:
//bool initFromPrevious(ObjectPtr theObject);
- /// Defines if the widget can be activated by mouse move.
- /// By default it returns false
- virtual bool canBeActivatedByMove();
-
/// The methiod called when widget is deactivated
virtual void deactivate();
/// and creating a coincidence constraint to them. This control use them.
virtual bool useSelectedShapes() const;
-signals:
- /// Signal about selection of an existing vertex from an object
- void vertexSelected();
-
-public slots:
- /// Process mouse move event
- /// \param theWnd a view window
+ /// Processing the mouse move event in the viewer
+ /// \param theWindow a view window
/// \param theEvent a mouse event
- void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+ virtual void mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent);
- /// Process mouse release event
- /// \param theWnd a view window
+ /// Processing the mouse release event in the viewer
+ /// \param theWindow a view window
/// \param theEvent a mouse event
- void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+ virtual void mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent);
+
+signals:
+ /// Signal about selection of an existing vertex from an object
+ void vertexSelected();
protected:
/// Saves the internal parameters to the given feature
return theCurrentPnt->distance(theFirstPnt);
}
-void PartSet_WidgetPoint2dDistance::activateCustom()
-{
- ModuleBase_IViewer* aViewer = myWorkshop->viewer();
- connect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*)));
- connect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)));
-}
-
-void PartSet_WidgetPoint2dDistance::deactivate()
-{
- ModuleBase_ModelWidget::deactivate();
- ModuleBase_IViewer* aViewer = myWorkshop->viewer();
- disconnect(aViewer, SIGNAL(mouseMove(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseMove(ModuleBase_IViewWindow*, QMouseEvent*)));
- disconnect(aViewer, SIGNAL(mouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)),
- this, SLOT(onMouseRelease(ModuleBase_IViewWindow*, QMouseEvent*)));
-}
-
-void PartSet_WidgetPoint2dDistance::onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
+void PartSet_WidgetPoint2dDistance::mouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
{
// the contex menu release by the right button should not be processed by this widget
if (theEvent->button() != Qt::LeftButton)
emit focusOutWidget(this);
}
-void PartSet_WidgetPoint2dDistance::onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
+void PartSet_WidgetPoint2dDistance::mouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
{
if (isEditingMode())
return;
#define PartSet_WidgetPoint2dDistance_H
#include "PartSet.h"
+#include "PartSet_MouseProcessor.h"
+
#include <ModuleBase_WidgetDoubleValue.h>
#include <ModelAPI_CompositeFeature.h>
* </point2ddistance>
* \endcode
*/
-class PARTSET_EXPORT PartSet_WidgetPoint2dDistance : public ModuleBase_WidgetDoubleValue
+class PARTSET_EXPORT PartSet_WidgetPoint2dDistance : public ModuleBase_WidgetDoubleValue,
+ public PartSet_MouseProcessor
{
Q_OBJECT
public:
/// \return a boolean value
virtual bool isValidSelectionCustom(const std::shared_ptr<ModuleBase_ViewerPrs>& theValue);
- /// The methiod called when widget is deactivated
- virtual void deactivate();
-
/// \returns the sketch instance
CompositeFeaturePtr sketch() const { return mySketch; }
/// Returns true if the event is processed.
virtual bool processEnter();
-public slots:
- /// Process of mouse move
- /// \param theWnd a pointer to a window
- /// \param theEvent a mouse event
- void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+ /// Processing the mouse move event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ virtual void mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent);
- protected slots:
- /// Process of mouse release
- /// \param theWnd a pointer to a window
- /// \param theEvent a mouse event
- void onMouseRelease(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+ /// Processing the mouse release event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ virtual void mouseReleased(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent);
protected:
/// Store current value in cashed value
/// \return true if the widget current value is reset
virtual bool resetCustom();
- /// The methiod called when widget is activated
- virtual void activateCustom();
-
/// Set the second point which defines a value in the widget as a distance with a first point defined by feature
void setPoint(FeaturePtr theFeature, const std::shared_ptr<GeomAPI_Pnt2d>& thePnt);
aValues.push_back(aValue);
aFOperation->setPreselection(aValues);
- myModule->sendOperation(aFOperation);
+ myWorkshop->processLaunchOperation(aFOperation);
return aSketchStarted;
}
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PartSet_WidgetSubShapeSelector.cpp
+// Created: 21 Jul 2016
+// Author: Natalia ERMOLAEVA
+
+#include "PartSet_WidgetSubShapeSelector.h"
+#include "PartSet_Tools.h"
+
+#include <ModuleBase_ISelection.h>
+#include <ModuleBase_ViewerPrs.h>
+
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Tools.h>
+#include <GeomDataAPI_Point2D.h>
+
+#include <GeomDataAPI_Point.h>
+
+#include <GeomAlgoAPI_ShapeTools.h>
+#include <ModelGeomAlgo_Point2D.h>
+
+#include <ModelGeomAlgo_Point2D.h>
+
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_Point.h>
+
+#include <ModuleBase_IViewWindow.h>
+#include <ModuleBase_IWorkshop.h>
+#include <ModuleBase_IModule.h>
+
+#include <Config_WidgetAPI.h>
+
+#include <QWidget>
+#include <QMouseEvent>
+
+PartSet_WidgetSubShapeSelector::PartSet_WidgetSubShapeSelector(QWidget* theParent,
+ ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData)
+: PartSet_WidgetShapeSelector(theParent, theWorkshop, theData)
+{
+ //myUseSketchPlane = theData->getBooleanAttribute("use_sketch_plane", true);
+ //myExternalObjectMgr = new PartSet_ExternalObjectsMgr(theData->getProperty("use_external"), true);
+}
+
+PartSet_WidgetSubShapeSelector::~PartSet_WidgetSubShapeSelector()
+{
+}
+
+//********************************************************************
+void PartSet_WidgetSubShapeSelector::mouseMoved(ModuleBase_IViewWindow* theWindow,
+ QMouseEvent* theEvent)
+{
+ ModuleBase_ISelection* aSelect = myWorkshop->selection();
+ QList<ModuleBase_ViewerPrsPtr> aHighlighted = aSelect->getHighlighted();
+
+ if (aHighlighted.empty()) {
+ ModuleBase_ViewerPrsPtr aPrs = aHighlighted.first();
+ if (aPrs.get() && aPrs->object().get()) {
+ ObjectPtr anObject = aPrs->object();
+ if (myCashedShapes.find(anObject) == myCashedShapes.end())
+ fillObjectShapes(anObject);
+ const std::set<GeomShapePtr>& aShapes = myCashedShapes[anObject];
+ if (!aShapes.empty()) {
+ gp_Pnt aPnt = PartSet_Tools::convertClickToPoint(theEvent->pos(), theWindow->v3dView());
+ std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(aPnt.X(), aPnt.Y(), aPnt.Z()));
+
+ std::set<GeomShapePtr>::const_iterator anIt = aShapes.begin(), aLast = aShapes.end();
+ for (; anIt != aLast; anIt++) {
+ GeomShapePtr aBaseShape = *anIt;
+ if (GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertexShape, aBaseShape)) {
+ myCurrentSubShape->setObject(anObject);
+ myCurrentSubShape->setShape(aBaseShape);
+ break;
+ }
+ }
+ }
+ }
+ }
+ myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects,
+ true);
+}
+
+//********************************************************************
+void PartSet_WidgetSubShapeSelector::getHighlighted(
+ QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues)
+{
+ if (myCurrentSubShape.get() && myCurrentSubShape->object().get())
+ theValues.append(myCurrentSubShape);
+}
+
+//********************************************************************
+void PartSet_WidgetSubShapeSelector::fillObjectShapes(const ObjectPtr& theObject)
+{
+ std::set<std::shared_ptr<GeomAPI_Shape> > aShapes;
+
+ // current feature
+ FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
+ std::set<GeomShapePtr> anEdgeShapes;
+ // edges on feature
+ ModelAPI_Tools::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
+ if (!anEdgeShapes.empty()) {
+ GeomShapePtr aFeatureShape = *anEdgeShapes.begin();
+
+ // coincidences to the feature
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
+ ModelGeomAlgo_Point2D::getPointsOfReference(aFeature, SketchPlugin_ConstraintCoincidence::ID(),
+ aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
+ // layed on feature coincidences to divide it on several shapes
+ FeaturePtr aSketch = sketch();
+ std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
+ std::shared_ptr<GeomDataAPI_Point> aC = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+ aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+ std::shared_ptr<GeomDataAPI_Dir> aX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
+ std::shared_ptr<GeomDataAPI_Dir> aNorm = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+ aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+ std::shared_ptr<GeomAPI_Dir> aY(new GeomAPI_Dir(aNorm->dir()->cross(aX->dir())));
+ std::set<std::shared_ptr<GeomAPI_Pnt> > aPoints;
+ ModelGeomAlgo_Point2D::getPointsInsideShape(aFeatureShape, aRefAttributes, aC->pnt(),
+ aX->dir(), aY, aPoints);
+
+ GeomAlgoAPI_ShapeTools::splitShape(aFeatureShape, aPoints, aShapes);
+ }
+ myCashedShapes[theObject] = aShapes;
+}
+
+//********************************************************************
+/*bool PartSet_WidgetSubShapeSelector::activateSelectionAndFilters(bool toActivate)
+{
+ bool aHasSelectionFilter = ModuleBase_WidgetShapeSelector::activateSelectionAndFilters
+ (toActivate);
+ if (!myUseSketchPlane) {
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(aWorkshop->module());
+ bool isUsePlaneFilterOnly = !toActivate;
+ aModule->sketchMgr()->activatePlaneFilter(isUsePlaneFilterOnly);
+ }
+ return aHasSelectionFilter;
+}
+
+//********************************************************************
+bool PartSet_WidgetSubShapeSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
+{
+ bool aValid = ModuleBase_WidgetShapeSelector::isValidSelectionCustom(thePrs);
+ if (aValid) {
+ ObjectPtr anObject = myWorkshop->selection()->getResult(thePrs);
+ aValid = myExternalObjectMgr->isValidObject(anObject);
+ }
+ return aValid;
+}
+
+void PartSet_WidgetSubShapeSelector::getGeomSelection(const ModuleBase_ViewerPrsPtr& thePrs,
+ ObjectPtr& theObject,
+ GeomShapePtr& theShape)
+{
+ ModuleBase_WidgetShapeSelector::getGeomSelection(thePrs, theObject, theShape);
+
+ FeaturePtr aSelectedFeature = ModelAPI_Feature::feature(theObject);
+ std::shared_ptr<SketchPlugin_Feature> aSPFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(aSelectedFeature);
+ // there is no a sketch feature is selected, but the shape exists, try to create an exernal object
+ // TODO: unite with the same functionality in PartSet_WidgetSubShapeSelector
+ if (aSPFeature.get() == NULL) {
+ ObjectPtr anExternalObject = ObjectPtr();
+ if (myExternalObjectMgr->useExternal()) {
+ GeomShapePtr aShape = theShape;
+ if (!aShape.get()) {
+ ResultPtr aResult = myWorkshop->selection()->getResult(thePrs);
+ if (aResult.get())
+ aShape = aResult->shape();
+ }
+ if (aShape.get() != NULL && !aShape->isNull())
+ anExternalObject = myExternalObjectMgr->externalObject(theObject, aShape, sketch(), myIsInValidate);
+ }
+ /// the object is null if the selected feature is "external"(not sketch entity feature of the
+ /// current sketch) and it is not created by object manager
+ theObject = anExternalObject;
+ }
+}
+
+//********************************************************************
+void PartSet_WidgetSubShapeSelector::restoreAttributeValue(const AttributePtr& theAttribute,
+ const bool theValid)
+{
+ ModuleBase_WidgetShapeSelector::restoreAttributeValue(theAttribute, theValid);
+ myExternalObjectMgr->removeExternal(sketch(), myFeature, myWorkshop, true);
+}
+*/
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PartSet_WidgetSubShapeSelector.h
+// Created: 21 Jul 2016
+// Author: Natalia ERMOLAEVA
+
+
+#ifndef PartSet_WidgetSubShapeSelector_H
+#define PartSet_WidgetSubShapeSelector_H
+
+#include "PartSet.h"
+
+#include <PartSet_WidgetShapeSelector.h>
+#include <PartSet_MouseProcessor.h>
+
+#include <QObject>
+
+#include <set>
+#include <map>
+
+class ModuleBase_IWorkshop;
+class Config_WidgetAPI;
+class ModuleBase_IViewWindow;
+class ModuleBase_ViewerPrs;
+
+class QWidget;
+class QMouseEvent;
+
+/**
+* \ingroup Modules
+* Customosation of PartSet_WidgetSubShapeSelector in order to visualize sub-shape
+* by mouse move over shape in the viewer. Split of the object is performed by
+* coincident points to the object. Segment between nearest coincidence is highlighted
+*/
+class PARTSET_EXPORT PartSet_WidgetSubShapeSelector: public PartSet_WidgetShapeSelector,
+ public PartSet_MouseProcessor
+{
+Q_OBJECT
+ public:
+ /// Constructor
+ /// \param theParent the parent object
+ /// \param theWorkshop instance of workshop interface
+ /// \param theData the widget configuation. The attribute of the model widget is obtained from
+ PartSet_WidgetSubShapeSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop,
+ const Config_WidgetAPI* theData);
+
+ virtual ~PartSet_WidgetSubShapeSelector();
+
+ /// Processing the mouse move event in the viewer
+ /// \param theWindow a view window
+ /// \param theEvent a mouse event
+ virtual void mouseMoved(ModuleBase_IViewWindow* theWindow, QMouseEvent* theEvent);
+
+ /// Returns values which should be highlighted when the whidget is active
+ /// \param theValues a list of presentations
+ virtual void getHighlighted(QList<std::shared_ptr<ModuleBase_ViewerPrs>>& theValues);
+
+protected:
+ /// Checks the widget validity. By default, it returns true.
+ /// \param thePrs a selected presentation in the view
+ /// \return a boolean value
+ //virtual bool isValidSelectionCustom(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs);
+
+ /// Return an object and geom shape by the viewer presentation
+ /// \param thePrs a selection
+ /// \param theObject an output object
+ /// \param theShape a shape of the selection
+ //virtual void getGeomSelection(const std::shared_ptr<ModuleBase_ViewerPrs>& thePrs,
+ // ObjectPtr& theObject,
+ // GeomShapePtr& theShape);
+ void fillObjectShapes(const ObjectPtr& theObject);
+
+protected:
+ std::shared_ptr<ModuleBase_ViewerPrs> myCurrentSubShape;
+ std::map<ObjectPtr, std::set<GeomShapePtr> > myCashedShapes;
+};
+
+#endif
\ No newline at end of file
SET(PROJECT_HEADERS
SketchPlugin.h
- SketchPlugin_Feature.h
- SketchPlugin_Plugin.h
- SketchPlugin_Sketch.h
- SketchPlugin_SketchEntity.h
- SketchPlugin_Line.h
- SketchPlugin_Point.h
- SketchPlugin_IntersectionPoint.h
- SketchPlugin_Circle.h
SketchPlugin_Arc.h
+ SketchPlugin_Circle.h
SketchPlugin_Constraint.h
+ SketchPlugin_ConstraintAngle.h
SketchPlugin_ConstraintBase.h
SketchPlugin_ConstraintCoincidence.h
SketchPlugin_ConstraintCollinear.h
SketchPlugin_ConstraintDistance.h
+ SketchPlugin_ConstraintEqual.h
+ SketchPlugin_ConstraintFillet.h
+ SketchPlugin_ConstraintHorizontal.h
SketchPlugin_ConstraintLength.h
SketchPlugin_ConstraintMiddle.h
+ SketchPlugin_ConstraintMirror.h
SketchPlugin_ConstraintParallel.h
SketchPlugin_ConstraintPerpendicular.h
SketchPlugin_ConstraintRadius.h
SketchPlugin_ConstraintRigid.h
- SketchPlugin_ConstraintHorizontal.h
- SketchPlugin_ConstraintVertical.h
- SketchPlugin_ConstraintEqual.h
+ SketchPlugin_ConstraintSplit.h
SketchPlugin_ConstraintTangent.h
- SketchPlugin_ConstraintMirror.h
- SketchPlugin_ConstraintFillet.h
- SketchPlugin_ConstraintAngle.h
+ SketchPlugin_ConstraintVertical.h
+ SketchPlugin_ExternalValidator.h
+ SketchPlugin_Feature.h
+ SketchPlugin_IntersectionPoint.h
+ SketchPlugin_Line.h
SketchPlugin_MultiRotation.h
SketchPlugin_MultiTranslation.h
- SketchPlugin_ExternalValidator.h
- SketchPlugin_Validators.h
- SketchPlugin_Tools.h
+ SketchPlugin_Plugin.h
+ SketchPlugin_Point.h
SketchPlugin_Projection.h
+ SketchPlugin_Sketch.h
+ SketchPlugin_SketchEntity.h
+ SketchPlugin_Tools.h
+ SketchPlugin_Validators.h
)
SET(PROJECT_SOURCES
- SketchPlugin_Feature.cpp
- SketchPlugin_Plugin.cpp
- SketchPlugin_Sketch.cpp
- SketchPlugin_SketchEntity.cpp
- SketchPlugin_Line.cpp
- SketchPlugin_Point.cpp
- SketchPlugin_IntersectionPoint.cpp
- SketchPlugin_Circle.cpp
SketchPlugin_Arc.cpp
+ SketchPlugin_Circle.cpp
SketchPlugin_Constraint.cpp
+ SketchPlugin_ConstraintAngle.cpp
SketchPlugin_ConstraintBase.cpp
SketchPlugin_ConstraintCoincidence.cpp
SketchPlugin_ConstraintCollinear.cpp
SketchPlugin_ConstraintDistance.cpp
+ SketchPlugin_ConstraintEqual.cpp
+ SketchPlugin_ConstraintFillet.cpp
+ SketchPlugin_ConstraintHorizontal.cpp
SketchPlugin_ConstraintLength.cpp
SketchPlugin_ConstraintMiddle.cpp
+ SketchPlugin_ConstraintMirror.cpp
SketchPlugin_ConstraintParallel.cpp
SketchPlugin_ConstraintPerpendicular.cpp
SketchPlugin_ConstraintRadius.cpp
SketchPlugin_ConstraintRigid.cpp
- SketchPlugin_ConstraintHorizontal.cpp
- SketchPlugin_ConstraintVertical.cpp
- SketchPlugin_ConstraintEqual.cpp
+ SketchPlugin_ConstraintSplit.cpp
SketchPlugin_ConstraintTangent.cpp
- SketchPlugin_ConstraintMirror.cpp
- SketchPlugin_ConstraintFillet.cpp
- SketchPlugin_ConstraintAngle.cpp
+ SketchPlugin_ConstraintVertical.cpp
+ SketchPlugin_ExternalValidator.cpp
+ SketchPlugin_Feature.cpp
+ SketchPlugin_IntersectionPoint.cpp
+ SketchPlugin_Line.cpp
SketchPlugin_MultiRotation.cpp
SketchPlugin_MultiTranslation.cpp
- SketchPlugin_ExternalValidator.cpp
- SketchPlugin_Validators.cpp
- SketchPlugin_Tools.cpp
+ SketchPlugin_Plugin.cpp
+ SketchPlugin_Point.cpp
SketchPlugin_Projection.cpp
+ SketchPlugin_Sketch.cpp
+ SketchPlugin_SketchEntity.cpp
+ SketchPlugin_Tools.cpp
+ SketchPlugin_Validators.cpp
)
SET(PROJECT_LIBRARIES
GeomAPI
GeomAlgoAPI
ModelAPI
+ ModelGeomAlgo
SketcherPrs
GeomDataAPI
)
../Config
../Events
../ModelAPI
+ ../ModelGeomAlgo
../GeomAPI
../GeomAlgoAPI
../GeomDataAPI
std::shared_ptr<GeomDataAPI_Point2D> aTangentPoint =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aTangPtAttr->attr());
std::shared_ptr<GeomAPI_Pnt2d> aTangPnt2d = aTangentPoint->pnt();
+ if (aTangPnt2d->isEqual(anEndAttr->pnt()))
+ return;
FeaturePtr aTangFeature = ModelAPI_Feature::feature(aTangentPoint->owner());
std::shared_ptr<GeomAPI_Edge> aTangEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(
aTangFeature->lastResult()->shape());
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_ConstraintSplit.cpp
+// Created: 17 Jul 2016
+// Author: Natalia ERMOLAEVA
+
+#include "SketchPlugin_ConstraintSplit.h"
+
+//#include <GeomAPI_Circ2d.h>
+//#include <GeomAPI_Dir2d.h>
+//#include <GeomAPI_Lin2d.h>
+//#include <GeomAPI_Pnt2d.h>
+//#include <GeomAPI_XY.h>
+//#include <GeomDataAPI_Point2D.h>
+//#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeSelection.h>
+//#include <ModelAPI_AttributeRefList.h>
+//#include <ModelAPI_AttributeRefAttrList.h>
+//#include <ModelAPI_Data.h>
+//#include <ModelAPI_Events.h>
+//#include <ModelAPI_Session.h>
+//#include <ModelAPI_Validator.h>
+//
+//#include <SketchPlugin_Arc.h>
+//#include <SketchPlugin_Line.h>
+//#include <SketchPlugin_Point.h>
+//#include <SketchPlugin_Sketch.h>
+//#include <SketchPlugin_ConstraintCoincidence.h>
+//#include <SketchPlugin_ConstraintTangent.h>
+//#include <SketchPlugin_ConstraintRadius.h>
+//#include <SketchPlugin_Tools.h>
+//
+//#include <Events_Loop.h>
+//
+//#include <math.h>
+//
+//const double tolerance = 1.e-7;
+//const double paramTolerance = 1.e-4;
+
+///// \brief Attract specified point on theNewArc to the attribute of theFeature
+//static void recalculateAttributes(FeaturePtr theNewArc, const std::string& theNewArcAttribute,
+// FeaturePtr theFeature, const std::string& theFeatureAttribute);
+//
+///// \brief Calculates center of fillet arc and coordinates of tangency points
+//static void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB,
+// double theRadius, bool theNotInversed[2],
+// std::shared_ptr<GeomAPI_XY>& theCenter,
+// std::shared_ptr<GeomAPI_XY>& theTangentA,
+// std::shared_ptr<GeomAPI_XY>& theTangentB);
+//
+///// Get point on 1/3 length of edge from fillet point
+//static void getPointOnEdge(const FeaturePtr theFeature,
+// const std::shared_ptr<GeomAPI_Pnt2d> theFilletPoint,
+// std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
+//
+///// Get distance from point to feature
+//static double getProjectionDistance(const FeaturePtr theFeature,
+// const std::shared_ptr<GeomAPI_Pnt2d> thePoint);
+//
+///// Get coincide edges for fillet
+//static std::set<FeaturePtr> getCoincides(const FeaturePtr& theConstraintCoincidence);
+
+SketchPlugin_ConstraintSplit::SketchPlugin_ConstraintSplit()
+//: myListOfPointsChangedInCode(false),
+// myRadiusChangedByUser(false),
+// myRadiusChangedInCode(false),
+// myRadiusInitialized(false)
+{
+}
+
+void SketchPlugin_ConstraintSplit::initAttributes()
+{
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeSelection::typeId());
+
+ //data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
+ //data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttrList::typeId());
+}
+
+void SketchPlugin_ConstraintSplit::execute()
+{
+/* std::shared_ptr<ModelAPI_Data> aData = data();
+
+ // Check the base objects are initialized.
+ AttributeRefAttrListPtr aPointsRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if(!aPointsRefList->isInitialized()) {
+ setError("Error: List of points is not initialized.");
+ return;
+ }
+
+ // Get fillet radius.
+ double aFilletRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ aData->attribute(SketchPlugin_Constraint::VALUE()))->value();
+
+ // Wait all constraints being created, then send update events
+ static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+ bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
+ if (isUpdateFlushed)
+ Events_Loop::loop()->setFlushed(anUpdateEvent, false);
+
+ for(std::set<AttributePtr>::iterator aPointsIter = myNewPoints.begin();
+ aPointsIter != myNewPoints.end();
+ ++aPointsIter) {
+ AttributePtr aPointAttr = *aPointsIter;
+ std::shared_ptr<GeomDataAPI_Point2D> aFilletPoint2d = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aPointAttr);
+ if(!aFilletPoint2d.get()) {
+ setError("Error: One of the selected points is empty.");
+ return;
+ }
+ std::shared_ptr<GeomAPI_Pnt2d> aFilletPnt2d = aFilletPoint2d->pnt();
+
+ // Obtain base lines for fillet.
+ bool anIsNeedNewObjects = true;
+ FilletFeatures aFilletFeatures;
+ std::map<AttributePtr, FilletFeatures>::iterator aPrevPointsIter = myPointFeaturesMap.find(aPointAttr);
+ if(aPrevPointsIter != myPointFeaturesMap.end()) {
+ anIsNeedNewObjects = false;
+ aFilletFeatures = aPrevPointsIter->second;
+ }
+ FeaturePtr aBaseEdgeA, aBaseEdgeB;
+ if(!anIsNeedNewObjects) {
+ aBaseEdgeA = aFilletFeatures.baseEdgesState.front().first;
+ aBaseEdgeB = aFilletFeatures.baseEdgesState.back().first;
+ } else {
+ // Obtain constraint coincidence for the fillet point.
+ FeaturePtr aConstraintCoincidence;
+ const std::set<AttributePtr>& aRefsList = aFilletPoint2d->owner()->data()->refsToMe();
+ for(std::set<AttributePtr>::const_iterator anIt = aRefsList.cbegin(); anIt != aRefsList.cend(); ++anIt) {
+ std::shared_ptr<ModelAPI_Attribute> anAttr = (*anIt);
+ FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
+ if(aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));
+ AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
+ if(anAttrRefA.get() && !anAttrRefA->isObject()) {
+ AttributePtr anAttrA = anAttrRefA->attr();
+ if(aFilletPoint2d == anAttrA) {
+ aConstraintCoincidence = aConstrFeature;
+ break;
+ }
+ }
+ if(anAttrRefB.get() && !anAttrRefB->isObject()) {
+ AttributePtr anAttrB = anAttrRefB->attr();
+ if(aFilletPoint2d == anAttrB) {
+ aConstraintCoincidence = aConstrFeature;
+ break;
+ }
+ }
+ }
+ }
+
+ if(!aConstraintCoincidence.get()) {
+ setError("Error: No coincident edges at one of the selected points.");
+ return;
+ }
+
+ // Get coincide edges.
+ std::set<FeaturePtr> aCoincides = getCoincides(aConstraintCoincidence);
+ if(aCoincides.size() != 2) {
+ setError("Error: One of the selected points does not have two suitable edges for fillet.");
+ return;
+ }
+
+ std::set<FeaturePtr>::iterator aLinesIt = aCoincides.begin();
+ aBaseEdgeA = *aLinesIt++;
+ aBaseEdgeB = *aLinesIt;
+
+ std::pair<FeaturePtr, bool> aBasePairA = std::make_pair(aBaseEdgeA, aBaseEdgeA->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
+ std::pair<FeaturePtr, bool> aBasePairB = std::make_pair(aBaseEdgeB, aBaseEdgeB->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
+ aFilletFeatures.baseEdgesState.push_back(aBasePairA);
+ aFilletFeatures.baseEdgesState.push_back(aBasePairB);
+ }
+
+ if(!aBaseEdgeA.get() || !aBaseEdgeB.get()) {
+ setError("Error: One of the base edges is empty.");
+ return;
+ }
+
+ // Create new edges and arc if needed.
+ FeaturePtr aResultEdgeA, aResultEdgeB, aResultArc;
+ if(!anIsNeedNewObjects) {
+ // Obtain features from the list.
+ std::list<FeaturePtr>::iterator aResultEdgesIt = aFilletFeatures.resultEdges.begin();
+ aResultEdgeA = *aResultEdgesIt++;
+ aResultEdgeB = *aResultEdgesIt++;
+ aResultArc = *aResultEdgesIt;
+ } else {
+ // Copy edges and create arc.
+ aResultEdgeA = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aBaseEdgeA, sketch());
+ aResultEdgeA->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(false);
+ aResultEdgeB = SketchPlugin_Sketch::addUniqueNamedCopiedFeature(aBaseEdgeB, sketch());
+ aResultEdgeB->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(false);
+ aResultArc = sketch()->addFeature(SketchPlugin_Arc::ID());
+
+ aFilletFeatures.resultEdges.push_back(aResultEdgeA);
+ aFilletFeatures.resultEdges.push_back(aResultEdgeB);
+ aFilletFeatures.resultEdges.push_back(aResultArc);
+ }
+
+ // Calculate arc attributes
+ static const int aNbFeatures = 2;
+ FeaturePtr aBaseFeatures[aNbFeatures] = {aBaseEdgeA, aBaseEdgeB};
+ FeaturePtr aResultFeatures[aNbFeatures] = {aResultEdgeA, aResultEdgeB};
+ std::shared_ptr<GeomAPI_Dir2d> aTangentDir[aNbFeatures]; // tangent directions of the features in coincident point
+ bool isStart[aNbFeatures]; // indicates which point the features share
+ std::shared_ptr<GeomAPI_Pnt2d> aStartEndPnt[aNbFeatures * 2]; // first pair of points relate to first feature, second pair - to second
+ std::string aFeatAttributes[aNbFeatures * 2]; // attributes of features
+ for (int i = 0; i < aNbFeatures; i++) {
+ std::string aStartAttr, aEndAttr;
+ if (aResultFeatures[i]->getKind() == SketchPlugin_Line::ID()) {
+ aStartAttr = SketchPlugin_Line::START_ID();
+ aEndAttr = SketchPlugin_Line::END_ID();
+ } else if (aResultFeatures[i]->getKind() == SketchPlugin_Arc::ID()) {
+ aStartAttr = SketchPlugin_Arc::START_ID();
+ aEndAttr = SketchPlugin_Arc::END_ID();
+ } else { // wrong argument
+ setError("Error: One of the points has wrong coincide feature");
+ return;
+ }
+ aFeatAttributes[2*i] = aStartAttr;
+ aStartEndPnt[2*i] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aBaseFeatures[i]->attribute(aStartAttr))->pnt();
+ aFeatAttributes[2*i+1] = aEndAttr;
+ aStartEndPnt[2*i+1] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aBaseFeatures[i]->attribute(aEndAttr))->pnt();
+ }
+ for (int aFeatInd = 0; aFeatInd < aNbFeatures; aFeatInd++) {
+ for (int j = 0; j < 2; j++) // loop on start-end of each feature
+ if (aStartEndPnt[aFeatInd * aNbFeatures + j]->distance(aFilletPnt2d) < 1.e-10) {
+ isStart[aFeatInd] = (j==0);
+ break;
+ }
+ }
+ // tangent directions of the features
+ for (int i = 0; i < aNbFeatures; i++) {
+ std::shared_ptr<GeomAPI_XY> aDir;
+ if (aResultFeatures[i]->getKind() == SketchPlugin_Line::ID()) {
+ aDir = aStartEndPnt[2*i+1]->xy()->decreased(aStartEndPnt[2*i]->xy());
+ if (!isStart[i])
+ aDir = aDir->multiplied(-1.0);
+ } else if (aResultFeatures[i]->getKind() == SketchPlugin_Arc::ID()) {
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aResultFeatures[i]->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+ aDir = isStart[i] ? aStartEndPnt[2*i]->xy() : aStartEndPnt[2*i+1]->xy();
+ aDir = aDir->decreased(aCenterPoint->xy());
+
+ double x = aDir->x();
+ double y = aDir->y();
+ aDir->setX(-y);
+ aDir->setY(x);
+ if (isStart[i] == std::dynamic_pointer_cast<SketchPlugin_Arc>(aBaseFeatures[i])->isReversed())
+ aDir = aDir->multiplied(-1.0);
+ }
+ aTangentDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aDir));
+ }
+
+ // By default, the start point of fillet arc is connected to FeatureA,
+ // and the end point - to FeatureB. But when the angle between TangentDirA and
+ // TangentDirB greater 180 degree, the sequaence of features need to be reversed.
+ double cosBA = aTangentDir[0]->cross(aTangentDir[1]); // cos(B-A), where A and B - angles between corresponding tanget direction and the X axis
+ bool isReversed = cosBA > 0.0;
+
+ // Calculate fillet arc parameters
+ std::shared_ptr<GeomAPI_XY> aCenter, aTangentPntA, aTangentPntB;
+ calculateFilletCenter(aBaseEdgeA, aBaseEdgeB, aFilletRadius, isStart, aCenter, aTangentPntA, aTangentPntB);
+ if(!aCenter.get() || !aTangentPntA.get() || !aTangentPntB.get()) {
+ setError("Can not create fillet with the specified parameters.");
+ return;
+ }
+ // update features
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aResultEdgeA->attribute(aFeatAttributes[isStart[0] ? 0 : 1]))->setValue(aTangentPntA->x(), aTangentPntA->y());
+ aResultEdgeA->execute();
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aResultEdgeB->attribute(aFeatAttributes[2 + (isStart[1] ? 0 : 1)]))->setValue(aTangentPntB->x(), aTangentPntB->y());
+ aResultEdgeB->execute();
+ // update fillet arc: make the arc correct for sure, so, it is not needed to process the "attribute updated"
+ // by arc; moreover, it may cause cyclicity in hte mechanism of updater
+ aResultArc->data()->blockSendAttributeUpdated(true);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aResultArc->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(aCenter->x(), aCenter->y());
+ if(isReversed) {
+ std::shared_ptr<GeomAPI_XY> aTmp = aTangentPntA;
+ aTangentPntA = aTangentPntB;
+ aTangentPntB = aTmp;
+ }
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aResultArc->attribute(SketchPlugin_Arc::START_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aResultArc->attribute(SketchPlugin_Arc::END_ID()));
+ if(aStartPoint->isInitialized() && aEndPoint->isInitialized() &&
+ (aStartPoint->pnt()->xy()->distance(aTangentPntA) > tolerance ||
+ aEndPoint->pnt()->xy()->distance(aTangentPntB) > tolerance)) {
+ std::dynamic_pointer_cast<SketchPlugin_Arc>(aResultArc)->setReversed(false);
+ }
+ aStartPoint->setValue(aTangentPntA->x(), aTangentPntA->y());
+ aEndPoint->setValue(aTangentPntB->x(), aTangentPntB->y());
+ aResultArc->data()->blockSendAttributeUpdated(false);
+ aResultArc->execute();
+
+ if(anIsNeedNewObjects) {
+ // Create list of additional constraints:
+ // 1. Coincidence of boundary points of features (copied lines/arcs) and fillet arc
+ // 1.1. coincidence
+ FeaturePtr aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ aRefAttr->setAttr(aResultArc->attribute(SketchPlugin_Arc::START_ID()));
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ int aFeatInd = isReversed ? 1 : 0;
+ int anAttrInd = (isReversed ? 2 : 0) + (isStart[isReversed ? 1 : 0] ? 0 : 1);
+ aRefAttr->setAttr(aResultFeatures[aFeatInd]->attribute(aFeatAttributes[anAttrInd]));
+ recalculateAttributes(aResultArc, SketchPlugin_Arc::START_ID(), aResultFeatures[aFeatInd], aFeatAttributes[anAttrInd]);
+ aConstraint->execute();
+ aFilletFeatures.resultConstraints.push_back(aConstraint);
+ ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
+ // 1.2. coincidence
+ aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ aRefAttr->setAttr(aResultArc->attribute(SketchPlugin_Arc::END_ID()));
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ aFeatInd = isReversed ? 0 : 1;
+ anAttrInd = (isReversed ? 0 : 2) + (isStart[isReversed ? 0 : 1] ? 0 : 1);
+ aRefAttr->setAttr(aResultFeatures[aFeatInd]->attribute(aFeatAttributes[anAttrInd]));
+ recalculateAttributes(aResultArc, SketchPlugin_Arc::END_ID(), aResultFeatures[aFeatInd], aFeatAttributes[anAttrInd]);
+ aConstraint->execute();
+ aFilletFeatures.resultConstraints.push_back(aConstraint);
+ ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
+ // 2. Fillet arc radius
+ //aConstraint = sketch()->addFeature(SketchPlugin_ConstraintRadius::ID());
+ //aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ // aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ //aRefAttr->setObject(aNewArc->lastResult());
+ //std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ // aConstraint->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aFilletRadius);
+ //std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ // aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()))->setValue(
+ // isStart[0] ? aStartEndPnt[0] : aStartEndPnt[1]);
+ //aConstraint->execute();
+ //myProducedFeatures.push_back(aConstraint);
+ //ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
+ // 3. Tangency of fillet arc and features
+ for (int i = 0; i < aNbFeatures; i++) {
+ aConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ aRefAttr->setObject(aResultArc->lastResult());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ bool isArc = aResultFeatures[i]->getKind() == SketchPlugin_Arc::ID();
+ aRefAttr->setObject(isArc ? aResultFeatures[i]->lastResult() : aResultFeatures[i]->firstResult());
+ aConstraint->execute();
+ aFilletFeatures.resultConstraints.push_back(aConstraint);
+ ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
+ }
+ // 4. Coincidence of free boundaries of base and copied features
+ for (int i = 0; i < aNbFeatures; i++) {
+ anAttrInd = 2*i + (isStart[i] ? 1 : 0);
+ aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ aRefAttr->setAttr(aBaseFeatures[i]->attribute(aFeatAttributes[anAttrInd]));
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ aRefAttr->setAttr(aResultFeatures[i]->attribute(aFeatAttributes[anAttrInd]));
+ aFilletFeatures.resultConstraints.push_back(aConstraint);
+ }
+ // 4.1. Additional tangency constraints when the fillet is based on arcs.
+ // It is used to verify the created arc will be placed on a source.
+ for (int i = 0; i < aNbFeatures; ++i) {
+ if (aResultFeatures[i]->getKind() != SketchPlugin_Arc::ID())
+ continue;
+ aConstraint = sketch()->addFeature(SketchPlugin_ConstraintTangent::ID());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ aRefAttr->setObject(aBaseFeatures[i]->lastResult());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ aRefAttr->setObject(aResultFeatures[i]->lastResult());
+ aConstraint->execute();
+ aFilletFeatures.resultConstraints.push_back(aConstraint);
+ ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
+ }
+ // 5. Tangent points should be placed on the base features
+ for (int i = 0; i < aNbFeatures; i++) {
+ anAttrInd = 2*i + (isStart[i] ? 0 : 1);
+ aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ aRefAttr->setAttr(aResultFeatures[i]->attribute(aFeatAttributes[anAttrInd]));
+ aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ aRefAttr->setObject(aBaseFeatures[i]->lastResult());
+ aFilletFeatures.resultConstraints.push_back(aConstraint);
+ }
+ // make base features auxiliary
+ aBaseEdgeA->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true);
+ aBaseEdgeB->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(true);
+
+ // exchange the naming IDs of newly created and old line that become auxiliary
+ sketch()->exchangeIDs(aBaseEdgeA, aResultEdgeA);
+ sketch()->exchangeIDs(aBaseEdgeB, aResultEdgeB);
+
+ // store point and features in the map.
+ myPointFeaturesMap[aPointAttr] = aFilletFeatures;
+ } else {
+ // Update radius value
+ int aNbSubs = sketch()->numberOfSubs();
+ FeaturePtr aSubFeature;
+ for (int aSub = 0; aSub < aNbSubs; aSub++) {
+ aSubFeature = sketch()->subFeature(aSub);
+ if (aSubFeature->getKind() != SketchPlugin_ConstraintRadius::ID())
+ continue;
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aSubFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ if (!aRefAttr || !aRefAttr->isObject())
+ continue;
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
+ if (aFeature == aResultArc) {
+ AttributeDoublePtr aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
+ aSubFeature->attribute(SketchPlugin_Constraint::VALUE()));
+ aRadius->setValue(aFilletRadius);
+ break;
+ }
+ }
+ }
+ }
+
+ // Send events to update the sub-features by the solver.
+ if(isUpdateFlushed) {
+ Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+ }
+*/
+}
+
+void SketchPlugin_ConstraintSplit::attributeChanged(const std::string& theID)
+{
+/* if(theID == SketchPlugin_Constraint::ENTITY_A()) {
+ if(myListOfPointsChangedInCode) {
+ return;
+ }
+
+ // Clear results.
+ clearResults();
+
+ // Clear list of new points.
+ myNewPoints.clear();
+
+ // Get list of points for fillets and current radius.
+ AttributeRefAttrListPtr aRefListOfFilletPoints = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttrList>(
+ data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeDoublePtr aRadiusAttribute = real(VALUE());
+ int aListSize = aRefListOfFilletPoints->size();
+ if(aListSize == 0 && !myRadiusChangedByUser) {
+ // If list is empty reset radius to zero (if it was not changed by user).
+ myRadiusChangedInCode = true;
+ aRadiusAttribute->setValue(0);
+ myRadiusChangedInCode = false;
+ return;
+ }
+
+ // Iterate over points to get base lines an calculate radius for fillets.
+ double aMinimumRadius = 0;
+ std::list<std::pair<ObjectPtr, AttributePtr>> aSelectedPointsList = aRefListOfFilletPoints->list();
+ std::list<std::pair<ObjectPtr, AttributePtr>>::iterator anIter = aSelectedPointsList.begin();
+ std::set<AttributePtr> aPointsToSkeep;
+ for(int anIndex = 0; anIndex < aListSize; anIndex++, anIter++) {
+ AttributePtr aFilletPointAttr = (*anIter).second;
+ std::shared_ptr<GeomDataAPI_Point2D> aFilletPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aFilletPointAttr);
+ if(!aFilletPoint2D.get()) {
+ myNewPoints.clear();
+ setError("Error: One of the selected points is invalid.");
+ return;
+ }
+
+ // If point or coincident point is already in list remove it from attribute.
+ if(aPointsToSkeep.find(aFilletPointAttr) != aPointsToSkeep.end()) {
+ myListOfPointsChangedInCode = true;
+ aRefListOfFilletPoints->remove(aFilletPointAttr);
+ myListOfPointsChangedInCode = false;
+ continue;
+ }
+
+ // Obtain constraint coincidence for the fillet point.
+ FeaturePtr aConstraintCoincidence;
+ const std::set<AttributePtr>& aRefsList = aFilletPointAttr->owner()->data()->refsToMe();
+ for(std::set<AttributePtr>::const_iterator anIt = aRefsList.cbegin(); anIt != aRefsList.cend(); ++anIt) {
+ std::shared_ptr<ModelAPI_Attribute> anAttr = (*anIt);
+ FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->owner());
+ if(aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));
+ AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
+ if(anAttrRefA.get()) {
+ AttributePtr anAttrA = anAttrRefA->attr();
+ if(aFilletPointAttr == anAttrA) {
+ aConstraintCoincidence = aConstrFeature;
+ break;
+ }
+ }
+ if(anAttrRefB.get()) {
+ AttributePtr anAttrB = anAttrRefB->attr();
+ if(aFilletPointAttr == anAttrB) {
+ aConstraintCoincidence = aConstrFeature;
+ break;
+ }
+ }
+ }
+ }
+
+ if(!aConstraintCoincidence.get()) {
+ myNewPoints.clear();
+ setError("Error: No coincident edges at one of the selected points.");
+ return;
+ }
+
+ // Get coincides from constraint.
+ std::set<FeaturePtr> aCoincides;
+
+
+ SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
+ SketchPlugin_ConstraintCoincidence::ENTITY_A(),
+ aCoincides);
+ SketchPlugin_Tools::findCoincidences(aConstraintCoincidence,
+ SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+ aCoincides);
+
+ // Remove points from set of coincides. Also get all attributes which is equal to this point to exclude it.
+ std::shared_ptr<GeomAPI_Pnt2d> aFilletPnt2d = aFilletPoint2D->pnt();
+ std::set<FeaturePtr> aNewSetOfCoincides;
+ for(std::set<FeaturePtr>::iterator anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) {
+ std::string aFeatureKind = (*anIt)->getKind();
+ if(aFeatureKind == SketchPlugin_Point::ID()) {
+ AttributePtr anAttr = (*anIt)->attribute(SketchPlugin_Point::COORD_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+ if(aPoint2D.get() && aFilletPnt2d->isEqual(aPoint2D->pnt())) {
+ aPointsToSkeep.insert(anAttr);
+ }
+ } else if(aFeatureKind == SketchPlugin_Line::ID()) {
+ AttributePtr anAttrStart = (*anIt)->attribute(SketchPlugin_Line::START_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointStart2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrStart);
+ if(aPointStart2D.get() && aFilletPnt2d->isEqual(aPointStart2D->pnt())) {
+ aPointsToSkeep.insert(anAttrStart);
+ }
+ AttributePtr anAttrEnd = (*anIt)->attribute(SketchPlugin_Line::END_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointEnd2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrEnd);
+ if(aPointEnd2D.get() && aFilletPnt2d->isEqual(aPointEnd2D->pnt())) {
+ aPointsToSkeep.insert(anAttrEnd);
+ }
+ aNewSetOfCoincides.insert(*anIt);
+ } else if(aFeatureKind == SketchPlugin_Arc::ID() ) {
+ AttributePtr anAttrCenter = (*anIt)->attribute(SketchPlugin_Arc::CENTER_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointCenter2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrCenter);
+ if(aPointCenter2D.get() && aFilletPnt2d->isEqual(aPointCenter2D->pnt())) {
+ aPointsToSkeep.insert(anAttrCenter);
+ continue;
+ }
+ AttributePtr anAttrStart = (*anIt)->attribute(SketchPlugin_Arc::START_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointStart2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrStart);
+ if(aPointStart2D.get() && aFilletPnt2d->isEqual(aPointStart2D->pnt())) {
+ aPointsToSkeep.insert(anAttrStart);
+ }
+ AttributePtr anAttrEnd = (*anIt)->attribute(SketchPlugin_Arc::END_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointEnd2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrEnd);
+ if(aPointEnd2D.get() && aFilletPnt2d->isEqual(aPointEnd2D->pnt())) {
+ aPointsToSkeep.insert(anAttrEnd);
+ }
+ aNewSetOfCoincides.insert(*anIt);
+ }
+ }
+ aCoincides = aNewSetOfCoincides;
+
+ // If we still have more than two coincides remove auxilary entities from set of coincides.
+ if(aCoincides.size() > 2) {
+ aNewSetOfCoincides.clear();
+ for(std::set<FeaturePtr>::iterator anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) {
+ if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) {
+ aNewSetOfCoincides.insert(*anIt);
+ }
+ }
+ aCoincides = aNewSetOfCoincides;
+ }
+
+ if(aCoincides.size() != 2) {
+ myNewPoints.clear();
+ setError("Error: One of the selected points does not have two suitable edges for fillet.");
+ return;
+ }
+
+ // Store base point for fillet.
+ aPointsToSkeep.insert(aFilletPointAttr);
+ myNewPoints.insert(aFilletPointAttr);
+
+ // Get base lines for fillet.
+ FeaturePtr anOldFeatureA, anOldFeatureB;
+ std::set<FeaturePtr>::iterator aLinesIt = aCoincides.begin();
+ anOldFeatureA = *aLinesIt++;
+ anOldFeatureB = *aLinesIt;
+
+ // Getting radius value if it was not changed by user.
+ if(!myRadiusChangedByUser) {
+ // Getting points located at 1/3 of edge length from fillet point.
+ std::shared_ptr<GeomAPI_Pnt2d> aFilletPnt2d = aFilletPoint2D->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPntA, aPntB;
+ getPointOnEdge(anOldFeatureA, aFilletPnt2d, aPntA);
+ getPointOnEdge(anOldFeatureB, aFilletPnt2d, aPntB);
+
+ /// Getting distances.
+ double aDistanceA = getProjectionDistance(anOldFeatureB, aPntA);
+ double aDistanceB = getProjectionDistance(anOldFeatureA, aPntB);
+ double aRadius = aDistanceA < aDistanceB ? aDistanceA / 2.0 : aDistanceB / 2.0;
+ aMinimumRadius = aMinimumRadius == 0 ? aRadius : aRadius < aMinimumRadius ? aRadius : aMinimumRadius;
+ }
+ }
+
+ // Set new default radius if it was not changed by user.
+ if(!myRadiusChangedByUser) {
+ myRadiusChangedInCode = true;
+ aRadiusAttribute->setValue(aMinimumRadius);
+ myRadiusChangedInCode = false;
+ }
+
+ } else if(theID == SketchPlugin_Constraint::VALUE()) {
+ if(myRadiusInitialized && !myRadiusChangedInCode) {
+ myRadiusChangedByUser = true;
+ }
+ if(!myRadiusInitialized) {
+ myRadiusInitialized = true;
+ }
+ }
+*/
+}
+
+//AISObjectPtr SketchPlugin_ConstraintSplit::getAISObject(AISObjectPtr thePrevious)
+//{
+// if (!sketch())
+// return thePrevious;
+//
+// AISObjectPtr anAIS = thePrevious;
+// /// TODO: Equal constraint presentation should be put here
+// return anAIS;
+//}
+
+bool SketchPlugin_ConstraintSplit::isMacro() const
+{
+ return true;
+}
+
+//void SketchPlugin_ConstraintSplit::clearResults()
+//{
+///* // Clear auxiliary flag on initial objects.
+// for(std::map<AttributePtr, FilletFeatures>::iterator aPointsIter = myPointFeaturesMap.begin();
+// aPointsIter != myPointFeaturesMap.end();) {
+// const FilletFeatures& aFilletFeatures = aPointsIter->second;
+// std::list<std::pair<FeaturePtr, bool>>::const_iterator aFeatureIt;
+// for(aFeatureIt = aFilletFeatures.baseEdgesState.cbegin();
+// aFeatureIt != aFilletFeatures.baseEdgesState.cend();
+// ++aFeatureIt) {
+// aFeatureIt->first->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(aFeatureIt->second);
+// }
+// ++aPointsIter;
+// }
+//
+// // And remove all produced features.
+// DocumentPtr aDoc = sketch()->document();
+// for(std::map<AttributePtr, FilletFeatures>::iterator aPointsIter = myPointFeaturesMap.begin();
+// aPointsIter != myPointFeaturesMap.end();) {
+// // Remove all produced constraints.
+// const FilletFeatures& aFilletFeatures = aPointsIter->second;
+// std::list<FeaturePtr>::const_iterator aFeatureIt;
+// for(aFeatureIt = aFilletFeatures.resultConstraints.cbegin();
+// aFeatureIt != aFilletFeatures.resultConstraints.cend();
+// ++aFeatureIt) {
+// aDoc->removeFeature(*aFeatureIt);
+// }
+//
+// // Remove all result edges.
+// for(aFeatureIt = aFilletFeatures.resultEdges.cbegin();
+// aFeatureIt != aFilletFeatures.resultEdges.cend();
+// ++aFeatureIt) {
+// aDoc->removeFeature(*aFeatureIt);
+// }
+//
+// // Remove point from map.
+// myPointFeaturesMap.erase(aPointsIter++);
+// }
+//*/
+//};
+//
+//
+//// ========= Auxiliary functions =================
+//void recalculateAttributes(FeaturePtr theNewArc, const std::string& theNewArcAttribute,
+// FeaturePtr theFeature, const std::string& theFeatureAttribute)
+//{
+// std::shared_ptr<GeomAPI_Pnt2d> anArcPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+// theNewArc->attribute(theNewArcAttribute))->pnt();
+// std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+// theFeature->attribute(theFeatureAttribute))->setValue(anArcPoint->x(), anArcPoint->y());
+//}
+
+/*/// \brief Find intersections of lines shifted along normal direction
+void possibleFilletCenterLineLine(
+ std::shared_ptr<GeomAPI_XY> thePointA, std::shared_ptr<GeomAPI_Dir2d> theDirA,
+ std::shared_ptr<GeomAPI_XY> thePointB, std::shared_ptr<GeomAPI_Dir2d> theDirB,
+ double theRadius, std::list< std::shared_ptr<GeomAPI_XY> >& theCenters)
+{
+ std::shared_ptr<GeomAPI_Dir2d> aDirAT(new GeomAPI_Dir2d(-theDirA->y(), theDirA->x()));
+ std::shared_ptr<GeomAPI_Dir2d> aDirBT(new GeomAPI_Dir2d(-theDirB->y(), theDirB->x()));
+ std::shared_ptr<GeomAPI_XY> aPntA, aPntB;
+ double aDet = theDirA->cross(theDirB);
+ for (double aStepA = -1.0; aStepA <= 1.0; aStepA += 2.0) {
+ aPntA = thePointA->added(aDirAT->xy()->multiplied(aStepA * theRadius));
+ for (double aStepB = -1.0; aStepB <= 1.0; aStepB += 2.0) {
+ aPntB = thePointB->added(aDirBT->xy()->multiplied(aStepB * theRadius));
+ double aVX = aDirAT->xy()->dot(aPntA);
+ double aVY = aDirBT->xy()->dot(aPntB);
+ std::shared_ptr<GeomAPI_XY> aPoint(new GeomAPI_XY(
+ (theDirB->x() * aVX - theDirA->x() * aVY) / aDet,
+ (theDirB->y() * aVX - theDirA->y() * aVY) / aDet));
+ theCenters.push_back(aPoint);
+ }
+ }
+}
+
+/// \brief Find intersections of line shifted along normal direction in both sides
+/// and a circle with extended radius
+void possibleFilletCenterLineArc(
+ std::shared_ptr<GeomAPI_XY> theStartLine, std::shared_ptr<GeomAPI_Dir2d> theDirLine,
+ std::shared_ptr<GeomAPI_XY> theCenterArc, double theRadiusArc,
+ double theRadius, std::list< std::shared_ptr<GeomAPI_XY> >& theCenters)
+{
+ std::shared_ptr<GeomAPI_Dir2d> aDirT(new GeomAPI_Dir2d(-theDirLine->y(), theDirLine->x()));
+ std::shared_ptr<GeomAPI_XY> aPnt;
+ double aDirNorm2 = theDirLine->dot(theDirLine);
+ double aRad = 0.0;
+ double aDirX = theDirLine->x();
+ double aDirX2 = theDirLine->x() * theDirLine->x();
+ double aDirY2 = theDirLine->y() * theDirLine->y();
+ double aDirXY = theDirLine->x() * theDirLine->y();
+ for (double aStepA = -1.0; aStepA <= 1.0; aStepA += 2.0) {
+ aPnt = theStartLine->added(aDirT->xy()->multiplied(aStepA * theRadius));
+ double aCoeff = aDirT->xy()->dot(aPnt->decreased(theCenterArc));
+ double aCoeff2 = aCoeff * aCoeff;
+ for (double aStepB = -1.0; aStepB <= 1.0; aStepB += 2.0) {
+ aRad = theRadiusArc + aStepB * theRadius;
+ double aD = aRad * aRad * aDirNorm2 - aCoeff2;
+ if (aD < 0.0)
+ continue;
+ double aDs = sqrt(aD);
+ double x1 = theCenterArc->x() + (aCoeff * aDirT->x() - aDirT->y() * aDs) / aDirNorm2;
+ double x2 = theCenterArc->x() + (aCoeff * aDirT->x() + aDirT->y() * aDs) / aDirNorm2;
+ double y1 = (aDirX2 * aPnt->y() + aDirY2 * theCenterArc->y() -
+ aDirXY * (aPnt->x() - theCenterArc->x()) - theDirLine->y() * aDs) / aDirNorm2;
+ double y2 = (aDirX2 * aPnt->y() + aDirY2 * theCenterArc->y() -
+ aDirXY * (aPnt->x() - theCenterArc->x()) + theDirLine->y() * aDs) / aDirNorm2;
+
+ std::shared_ptr<GeomAPI_XY> aPoint1(new GeomAPI_XY(x1, y1));
+ theCenters.push_back(aPoint1);
+ std::shared_ptr<GeomAPI_XY> aPoint2(new GeomAPI_XY(x2, y2));
+ theCenters.push_back(aPoint2);
+ }
+ }
+}
+
+/// \brief Find intersections of two circles with extended radii
+void possibleFilletCenterArcArc(
+ std::shared_ptr<GeomAPI_XY> theCenterA, double theRadiusA,
+ std::shared_ptr<GeomAPI_XY> theCenterB, double theRadiusB,
+ double theRadius, std::list< std::shared_ptr<GeomAPI_XY> >& theCenters)
+{
+ std::shared_ptr<GeomAPI_XY> aCenterDir = theCenterB->decreased(theCenterA);
+ double aCenterDist2 = aCenterDir->dot(aCenterDir);
+ double aCenterDist = sqrt(aCenterDist2);
+
+ double aRadA, aRadB;
+ for (double aStepA = -1.0; aStepA <= 1.0; aStepA += 2.0) {
+ aRadA = theRadiusA + aStepA * theRadius;
+ for (double aStepB = -1.0; aStepB <= 1.0; aStepB += 2.0) {
+ aRadB = theRadiusB + aStepB * theRadius;
+ if (aRadA + aRadB < aCenterDist || fabs(aRadA - aRadB) > aCenterDist)
+ continue; // there is no intersections
+
+ double aMedDist = (aRadA * aRadA - aRadB * aRadB + aCenterDist2) / (2.0 * aCenterDist);
+ double aHeight = sqrt(aRadA * aRadA - aMedDist * aMedDist);
+
+ double x1 = theCenterA->x() + (aMedDist * aCenterDir->x() + aCenterDir->y() * aHeight) / aCenterDist;
+ double y1 = theCenterA->y() + (aMedDist * aCenterDir->y() - aCenterDir->x() * aHeight) / aCenterDist;
+
+ double x2 = theCenterA->x() + (aMedDist * aCenterDir->x() - aCenterDir->y() * aHeight) / aCenterDist;
+ double y2 = theCenterA->y() + (aMedDist * aCenterDir->y() + aCenterDir->x() * aHeight) / aCenterDist;
+
+ std::shared_ptr<GeomAPI_XY> aPoint1(new GeomAPI_XY(x1, y1));
+ theCenters.push_back(aPoint1);
+ std::shared_ptr<GeomAPI_XY> aPoint2(new GeomAPI_XY(x2, y2));
+ theCenters.push_back(aPoint2);
+ }
+ }
+}
+
+void calculateFilletCenter(FeaturePtr theFeatureA, FeaturePtr theFeatureB,
+ double theRadius, bool theNotInversed[2],
+ std::shared_ptr<GeomAPI_XY>& theCenter,
+ std::shared_ptr<GeomAPI_XY>& theTangentA,
+ std::shared_ptr<GeomAPI_XY>& theTangentB)
+{
+ static const int aNbFeatures = 2;
+ FeaturePtr aFeature[aNbFeatures] = {theFeatureA, theFeatureB};
+ std::shared_ptr<GeomAPI_XY> aStart[aNbFeatures], aEnd[aNbFeatures], aCenter[aNbFeatures];
+ std::shared_ptr<GeomDataAPI_Point2D> aStartPoint, aEndPoint;
+
+ for (int i = 0; i < aNbFeatures; i++) {
+ if (aFeature[i]->getKind() == SketchPlugin_Line::ID()) {
+ aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature[i]->attribute(SketchPlugin_Line::START_ID()));
+ aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature[i]->attribute(SketchPlugin_Line::END_ID()));
+ } else if (aFeature[i]->getKind() == SketchPlugin_Arc::ID()) {
+ aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature[i]->attribute(SketchPlugin_Arc::START_ID()));
+ aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature[i]->attribute(SketchPlugin_Arc::END_ID()));
+ aCenter[i] = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aFeature[i]->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt()->xy();
+ } else
+ return;
+ aStart[i] = std::shared_ptr<GeomAPI_XY>(theNotInversed[i] ?
+ new GeomAPI_XY(aStartPoint->x(), aStartPoint->y()) :
+ new GeomAPI_XY(aEndPoint->x(), aEndPoint->y()));
+ aEnd[i] = std::shared_ptr<GeomAPI_XY>(theNotInversed[i] ?
+ new GeomAPI_XY(aEndPoint->x(), aEndPoint->y()) :
+ new GeomAPI_XY(aStartPoint->x(), aStartPoint->y()));
+ }
+
+ if (theFeatureA->getKind() == SketchPlugin_Line::ID() &&
+ theFeatureB->getKind() == SketchPlugin_Line::ID()) {
+ std::shared_ptr<GeomAPI_Dir2d> aDir[2];
+ std::shared_ptr<GeomAPI_Dir2d> aDirT[2];
+ for (int i = 0; i < aNbFeatures; i++) {
+ aDir[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aEnd[i]->decreased(aStart[i])));
+ aDirT[i] = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(-aDir[i]->y(), aDir[i]->x()));
+ }
+
+ // get and filter possible centers
+ std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
+ possibleFilletCenterLineLine(aStart[0], aDir[0], aStart[1], aDir[1], theRadius, aSuspectCenters);
+ double aDot = 0.0;
+ std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
+ for (; anIt != aSuspectCenters.end(); anIt++) {
+ aDot = aDirT[0]->xy()->dot(aStart[0]->decreased(*anIt));
+ theTangentA = (*anIt)->added(aDirT[0]->xy()->multiplied(aDot));
+ if (theTangentA->decreased(aStart[0])->dot(aDir[0]->xy()) < 0.0)
+ continue; // incorrect position
+ aDot = aDirT[1]->xy()->dot(aStart[1]->decreased(*anIt));
+ theTangentB = (*anIt)->added(aDirT[1]->xy()->multiplied(aDot));
+ if (theTangentB->decreased(aStart[1])->dot(aDir[1]->xy()) < 0.0)
+ continue; // incorrect position
+ // the center is found, stop searching
+ theCenter = *anIt;
+ return;
+ }
+ } else if ((theFeatureA->getKind() == SketchPlugin_Arc::ID() &&
+ theFeatureB->getKind() == SketchPlugin_Line::ID()) ||
+ (theFeatureA->getKind() == SketchPlugin_Line::ID() &&
+ theFeatureB->getKind() == SketchPlugin_Arc::ID())) {
+ int aLineInd = theFeatureA->getKind() == SketchPlugin_Line::ID() ? 0 : 1;
+ double anArcRadius = aStart[1-aLineInd]->distance(aCenter[1-aLineInd]);
+ std::shared_ptr<GeomAPI_Dir2d> aDirLine = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(aEnd[aLineInd]->decreased(aStart[aLineInd])));
+ std::shared_ptr<GeomAPI_Dir2d> aDirT = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(-aDirLine->y(), aDirLine->x()));
+
+ std::shared_ptr<GeomAPI_Dir2d> aStartArcDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(aStart[1-aLineInd]->decreased(aCenter[1-aLineInd])));
+ std::shared_ptr<GeomAPI_Dir2d> aEndArcDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(aEnd[1-aLineInd]->decreased(aCenter[1-aLineInd])));
+ double anArcAngle = aEndArcDir->angle(aStartArcDir);
+
+ // get possible centers and filter them
+ std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
+ possibleFilletCenterLineArc(aStart[aLineInd], aDirLine, aCenter[1-aLineInd], anArcRadius, theRadius, aSuspectCenters);
+ double aDot = 0.0;
+ // the line is forward into the arc
+ double innerArc = aCenter[1-aLineInd]->decreased(aStart[aLineInd])->dot(aDirLine->xy());
+ std::shared_ptr<GeomAPI_XY> aLineTgPoint, anArcTgPoint;
+ // The possible centers are ranged by their positions.
+ // If the point is not satisfy one of criteria, the weight is decreased with penalty.
+ int aBestWeight = 0;
+ std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
+ for (; anIt != aSuspectCenters.end(); anIt++) {
+ int aWeight = 2;
+ aDot = aDirT->xy()->dot(aStart[aLineInd]->decreased(*anIt));
+ aLineTgPoint = (*anIt)->added(aDirT->xy()->multiplied(aDot));
+ // Check the point is placed on the correct arc (penalty if false)
+ if (aCenter[1-aLineInd]->distance(*anIt) * innerArc > anArcRadius * innerArc)
+ aWeight -= 1;
+ std::shared_ptr<GeomAPI_Dir2d> aCurDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d((*anIt)->decreased(aCenter[1-aLineInd])));
+ double aCurAngle = aCurDir->angle(aStartArcDir);
+ if (anArcAngle < 0.0) aCurAngle *= -1.0;
+ if (aCurAngle < 0.0 || aCurAngle > fabs(anArcAngle))
+ continue;
+ if (aWeight > aBestWeight)
+ aBestWeight = aWeight;
+ else if (aWeight < aBestWeight ||
+ aStart[aLineInd]->distance(*anIt) >
+ aStart[aLineInd]->distance(theCenter)) // <-- take closer point
+ continue;
+ // the center is found, stop searching
+ theCenter = *anIt;
+ anArcTgPoint = aCenter[1-aLineInd]->added(aCurDir->xy()->multiplied(anArcRadius));
+ if (theFeatureA->getKind() == SketchPlugin_Line::ID()) {
+ theTangentA = aLineTgPoint;
+ theTangentB = anArcTgPoint;
+ } else {
+ theTangentA = anArcTgPoint;
+ theTangentB = aLineTgPoint;
+ }
+ //return;
+ }
+ } else if (theFeatureA->getKind() == SketchPlugin_Arc::ID() &&
+ theFeatureB->getKind() == SketchPlugin_Arc::ID()) {
+ double anArcRadius[aNbFeatures];
+ double anArcAngle[aNbFeatures];
+ std::shared_ptr<GeomAPI_Dir2d> aStartArcDir[aNbFeatures];
+ for (int i = 0; i < aNbFeatures; i++) {
+ anArcRadius[i] = aStart[i]->distance(aCenter[i]);
+ aStartArcDir[i] = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(aStart[i]->decreased(aCenter[i])));
+ std::shared_ptr<GeomAPI_Dir2d> aEndArcDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d(aEnd[i]->decreased(aCenter[i])));
+ anArcAngle[i] = aEndArcDir->angle(aStartArcDir[i]);
+ }
+
+ // get and filter possible centers
+ std::list< std::shared_ptr<GeomAPI_XY> > aSuspectCenters;
+ possibleFilletCenterArcArc(aCenter[0], anArcRadius[0], aCenter[1], anArcRadius[1], theRadius, aSuspectCenters);
+ double aDot = 0.0;
+ std::shared_ptr<GeomAPI_XY> aLineTgPoint, anArcTgPoint;
+ std::list< std::shared_ptr<GeomAPI_XY> >::iterator anIt = aSuspectCenters.begin();
+ for (; anIt != aSuspectCenters.end(); anIt++) {
+ std::shared_ptr<GeomAPI_Dir2d> aCurDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d((*anIt)->decreased(aCenter[0])));
+ double aCurAngle = aCurDir->angle(aStartArcDir[0]);
+ if (anArcAngle[0] < 0.0) aCurAngle *= -1.0;
+ if (aCurAngle < 0.0 || aCurAngle > fabs(anArcAngle[0]))
+ continue; // incorrect position
+ theTangentA = aCenter[0]->added(aCurDir->xy()->multiplied(anArcRadius[0]));
+
+ aCurDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d((*anIt)->decreased(aCenter[1])));
+ aCurAngle = aCurDir->angle(aStartArcDir[1]);
+ if (anArcAngle[1] < 0.0) aCurAngle *= -1.0;
+ if (aCurAngle < 0.0 || aCurAngle > fabs(anArcAngle[1]))
+ continue; // incorrect position
+ theTangentB = aCenter[1]->added(aCurDir->xy()->multiplied(anArcRadius[1]));
+
+ // the center is found, stop searching
+ theCenter = *anIt;
+ return;
+ }
+ }
+}
+
+void getPointOnEdge(const FeaturePtr theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d> theFilletPoint,
+ std::shared_ptr<GeomAPI_Pnt2d>& thePoint) {
+ if(theFeature->getKind() == SketchPlugin_Line::ID()) {
+ std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt();
+ if(aPntStart->distance(theFilletPoint) > 1.e-7) {
+ aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt();
+ aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt();
+ }
+ thePoint.reset( new GeomAPI_Pnt2d(aPntStart->xy()->added( aPntEnd->xy()->decreased( aPntStart->xy() )->multiplied(1.0 / 3.0) ) ) );
+ } else {
+ std::shared_ptr<GeomAPI_Pnt2d> aPntTemp;
+ std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
+ if(theFeature->attribute(SketchPlugin_Arc::INVERSED_ID())) {
+ aPntTemp = aPntStart;
+ aPntStart = aPntEnd;
+ aPntEnd = aPntTemp;
+ }
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Circ2d> aCirc(new GeomAPI_Circ2d(aCenterPnt, aPntStart));
+ double aStartParameter(0), anEndParameter(0);
+ aCirc->parameter(aPntStart, paramTolerance, aStartParameter);
+ aCirc->parameter(aPntEnd, paramTolerance, anEndParameter);
+ if(aPntStart->distance(theFilletPoint) > tolerance) {
+ double aTmpParameter = aStartParameter;
+ aStartParameter = anEndParameter;
+ anEndParameter = aTmpParameter;
+ }
+ double aPntParameter = aStartParameter + (anEndParameter - aStartParameter) / 3.0;
+ aCirc->D0(aPntParameter, thePoint);
+ }
+}
+
+double getProjectionDistance(const FeaturePtr theFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d> thePoint)
+{
+ std::shared_ptr<GeomAPI_Pnt2d> aProjectPnt;
+ if(theFeature->getKind() == SketchPlugin_Line::ID()) {
+ std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::START_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::END_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Lin2d> aLin(new GeomAPI_Lin2d(aPntStart, aPntEnd));
+ aProjectPnt = aLin->project(thePoint);
+ } else {
+ std::shared_ptr<GeomAPI_Pnt2d> aPntStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::START_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPntEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::END_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
+ std::shared_ptr<GeomAPI_Circ2d> aCirc(new GeomAPI_Circ2d(aCenterPnt, aPntStart));
+ aProjectPnt = aCirc->project(thePoint);
+ }
+ if(aProjectPnt.get()) {
+ return aProjectPnt->distance(thePoint);
+ }
+ return -1;
+}
+
+std::set<FeaturePtr> getCoincides(const FeaturePtr& theConstraintCoincidence)
+{
+ std::set<FeaturePtr> aCoincides;
+
+ std::shared_ptr<GeomAPI_Pnt2d> aFilletPnt = SketchPlugin_Tools::getCoincidencePoint(theConstraintCoincidence);
+
+ SketchPlugin_Tools::findCoincidences(theConstraintCoincidence,
+ SketchPlugin_ConstraintCoincidence::ENTITY_A(),
+ aCoincides);
+ SketchPlugin_Tools::findCoincidences(theConstraintCoincidence,
+ SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+ aCoincides);
+
+ // Remove points from set of coincides.
+ std::set<FeaturePtr> aNewSetOfCoincides;
+ for(std::set<FeaturePtr>::iterator anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) {
+ if((*anIt)->getKind() == SketchPlugin_Line::ID()) {
+ aNewSetOfCoincides.insert(*anIt);
+ } else if((*anIt)->getKind() == SketchPlugin_Arc::ID()) {
+ AttributePtr anAttrCenter = (*anIt)->attribute(SketchPlugin_Arc::CENTER_ID());
+ std::shared_ptr<GeomDataAPI_Point2D> aPointCenter2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrCenter);
+ if(aPointCenter2D.get() && aFilletPnt->isEqual(aPointCenter2D->pnt())) {
+ continue;
+ }
+ aNewSetOfCoincides.insert(*anIt);
+ }
+ }
+ aCoincides = aNewSetOfCoincides;
+
+ // If we still have more than two coincides remove auxilary entities from set of coincides.
+ if(aCoincides.size() > 2) {
+ aNewSetOfCoincides.clear();
+ for(std::set<FeaturePtr>::iterator anIt = aCoincides.begin(); anIt != aCoincides.end(); ++anIt) {
+ if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) {
+ aNewSetOfCoincides.insert(*anIt);
+ }
+ }
+ aCoincides = aNewSetOfCoincides;
+ }
+
+ return aCoincides;
+}
+*/
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
+
+// File: SketchPlugin_ConstraintSplit.h
+// Created: 19 Mar 2015
+// Author: Artem ZHIDKOV
+
+#ifndef SketchPlugin_ConstraintSplit_H_
+#define SketchPlugin_ConstraintSplit_H_
+
+#include "SketchPlugin.h"
+#include <SketchPlugin_Sketch.h>
+#include "SketchPlugin_ConstraintBase.h"
+
+/** \class SketchPlugin_ConstraintSplit
+ * \ingroup Plugins
+ * \brief Feature for creation of a new constraint filleting two objects which have coincident point
+ *
+ * This constraint has three attributes:
+ * SketchPlugin_Constraint::ENTITY_A() and SketchPlugin_Constraint::ENTITY_B() for the filleting objects;
+ * SketchPlugin_Constraint::VALUE() contains radius of filleting circular arc
+ *
+ * Also the constraint has attribute SketchPlugin_Constraint::ENTITY_C()
+ * which contains created list objects forming the fillet
+ */
+class SketchPlugin_ConstraintSplit : public SketchPlugin_ConstraintBase
+{
+ public:
+ /*struct FilletFeatures {
+ std::list<std::pair<FeaturePtr, bool>> baseEdgesState; ///< list of objects the fillet is based and its states
+ std::list<FeaturePtr> resultEdges; ///< list of result edges
+ std::list<FeaturePtr> resultConstraints; ///< list of constraints provided by the fillet
+ };*/
+
+ /// Split constraint kind
+ inline static const std::string& ID()
+ {
+ static const std::string MY_CONSTRAINT_SPLIT_ID("SketchConstraintSplit");
+ return MY_CONSTRAINT_SPLIT_ID;
+ }
+ /// \brief Returns the kind of a feature
+ SKETCHPLUGIN_EXPORT virtual const std::string& getKind()
+ {
+ static std::string MY_KIND = SketchPlugin_ConstraintSplit::ID();
+ return MY_KIND;
+ }
+
+ /// \brief Creates a new part document if needed
+ SKETCHPLUGIN_EXPORT virtual void execute();
+
+ /// \brief Request for initialization of data model of the feature: adding all attributes
+ SKETCHPLUGIN_EXPORT virtual void initAttributes();
+
+ /// Called on change of any argument-attribute of this object
+ /// \param theID identifier of changed attribute
+ SKETCHPLUGIN_EXPORT virtual void attributeChanged(const std::string& theID);
+
+ /// Returns the AIS preview
+ //SKETCHPLUGIN_EXPORT virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious);
+
+ /// Reimplemented from ModelAPI_Feature::isMacro().
+ /// \returns true
+ SKETCHPLUGIN_EXPORT virtual bool isMacro() const;
+
+ /// \brief Use plugin manager for features creation
+ SketchPlugin_ConstraintSplit();
+
+ /// \return map of base points and features;
+ //SKETCHPLUGIN_EXPORT const std::map<AttributePtr, FilletFeatures> pointsFeaturesMap() const {
+ // return myPointFeaturesMap;
+ //};
+
+private:
+ /// \ Removes all produced features and restore base edges.
+ //void clearResults();
+
+private:
+ //std::set<AttributePtr> myNewPoints; ///< set of new points
+ //std::map<AttributePtr, FilletFeatures> myPointFeaturesMap; ///< map of point and features for fillet
+ //bool myListOfPointsChangedInCode; ///< flag to track that list of points changed in code
+ //bool myRadiusChangedByUser; ///< flag to track that radius changed by user
+ //bool myRadiusChangedInCode; ///< flag to track that radius changed in code
+ //bool myRadiusInitialized; /// < flag to track that radius initialized
+};
+
+#endif
#include <SketchPlugin_ConstraintDistance.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintFillet.h>
+#include <SketchPlugin_ConstraintSplit.h>
#include <SketchPlugin_ConstraintHorizontal.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMiddle.h>
new SketchPlugin_SolverErrorValidator);
aFactory->registerValidator("SketchPlugin_FilletVertexValidator",
new SketchPlugin_FilletVertexValidator);
+ aFactory->registerValidator("SketchPlugin_SplitValidator",
+ new SketchPlugin_SplitValidator);
aFactory->registerValidator("SketchPlugin_MiddlePointAttr",
new SketchPlugin_MiddlePointAttrValidator);
aFactory->registerValidator("SketchPlugin_ArcTangentPoint",
return FeaturePtr(new SketchPlugin_ConstraintMirror);
} else if (theFeatureID == SketchPlugin_ConstraintFillet::ID()) {
return FeaturePtr(new SketchPlugin_ConstraintFillet);
+ } else if (theFeatureID == SketchPlugin_ConstraintSplit::ID()) {
+ return FeaturePtr(new SketchPlugin_ConstraintSplit);
} else if (theFeatureID == SketchPlugin_MultiTranslation::ID()) {
return FeaturePtr(new SketchPlugin_MultiTranslation);
} else if (theFeatureID == SketchPlugin_MultiRotation::ID()) {
aMsg->setState(SketchPlugin_ConstraintMiddle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintMirror::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintFillet::ID(), aHasSketchPlane);
+ aMsg->setState(SketchPlugin_ConstraintSplit::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_ConstraintAngle::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MultiRotation::ID(), aHasSketchPlane);
aMsg->setState(SketchPlugin_MultiTranslation::ID(), aHasSketchPlane);
#include <ModelAPI_AttributeSelectionList.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
#include <ModelAPI_ResultConstruction.h>
+#include <ModelGeomAlgo_Point2D.h>
+
#include <GeomAPI_Circ.h>
#include <GeomAPI_Lin.h>
#include <GeomAPI_Edge.h>
return fabs(aNormal->dot(aLineDir)) > tolerance * tolerance;
}
+bool SketchPlugin_SplitValidator::isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const
+{
+ bool aValid = false;
+
+ if (theAttribute->attributeType() != ModelAPI_AttributeSelection::typeId()) {
+ theError = "The attribute with the %1 type is not processed";
+ theError.arg(theAttribute->attributeType());
+ return aValid;
+ }
+ AttributeSelectionPtr aFeatureAttr =
+ std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+
+ ObjectPtr anAttrObject = aFeatureAttr->context();
+ FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttrObject);
+ if (!anAttrFeature)
+ return aValid;
+
+ std::string aKind = anAttrFeature->getKind();
+ if (aKind == SketchPlugin_Line::ID() ||
+ aKind == SketchPlugin_Arc::ID() ||
+ aKind == SketchPlugin_Circle::ID()) {
+
+ std::set<GeomShapePtr> anEdgeShapes;
+ ModelAPI_Tools::shapesOfType(anAttrFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
+ if (anEdgeShapes.empty())
+ return aValid;
+
+ GeomShapePtr anAttrShape = *anEdgeShapes.begin();
+
+ //std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
+ // anAttrFeature, theAttribute, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
+
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> > aRefAttributes;
+ //ModelGeomAlgo_Point2D::getPointsOfReference(anAttrFeature.get(), SketchPlugin_ConstraintCoincidence::ID(),
+ // aRefAttributes, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
+
+ //ModelGeomAlgo_Point2D::filterPointsToBeInsideShape(anAttrShape, aRefAttributes, );
+
+ int aCoincidentToFeature = aRefAttributes.size();
+ if (aKind == SketchPlugin_Circle::ID())
+ aValid = aCoincidentToFeature > 2;
+ else
+ aValid = aCoincidentToFeature > 1;
+ }
+
+ return true;
+}
+
bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
const std::list<std::string>& theArguments,
Events_InfoMessage& theError) const
Events_InfoMessage& theError) const;
};
+/**\class SketchPlugin_SplitValidator
+ * \ingroup Validators
+ * \brief Validator for the entity of the following type:
+ * - Linear segment with point(s) coinident to this line
+ * - Arc with point(s) coincident to the arc
+ * - Circle with at least 2 split-points on this circle
+ *
+ * Checks that there are coincident point on selected feature.
+ */
+class SketchPlugin_SplitValidator : public ModelAPI_AttributeValidator
+{
+ public:
+ //! returns true if attribute is valid
+ //! \param theAttribute the checked attribute
+ //! \param theArguments arguments of the attribute
+ //! \param theError error message
+ virtual bool isValid(const AttributePtr& theAttribute,
+ const std::list<std::string>& theArguments,
+ Events_InfoMessage& theError) const;
+};
+
/**\class SketchPlugin_IntersectionValidator
* \ingroup Validators
* \brief Validator for the attribute to be intersected with the sketch plane.
<translation>Second object is not selected</translation>
</message>
</context>
-
+
+ <context>
+ <name>SketchConstraintSplit</name>
+ <message>
+ <source>ConstraintEntityA - SketchPlugin_SplitValidator: The attribute with the %1 type is not processed</source>
+ <translation>Only attribute selection can be used for the sketch face, not %1</translation>
+ </message>
+ </context>
+
<context>
<name>SketchConstraintFillet</name>
<message>
<group id="Linear geometry">
<feature
id="Sketch"
- nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchArc SketchRectangle SketchProjection SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintCoincidence SketchConstraintMirror SketchConstraintAngle SketchMultiRotation SketchMultiTranslation SketchConstraintCollinear SketchConstraintMiddle"
+ nested="SketchPoint SketchIntersectionPoint SketchLine SketchCircle SketchArc SketchRectangle SketchProjection SketchConstraintLength SketchConstraintRadius SketchConstraintDistance SketchConstraintParallel SketchConstraintPerpendicular SketchConstraintRigid SketchConstraintHorizontal SketchConstraintVertical SketchConstraintEqual SketchConstraintTangent SketchConstraintFillet SketchConstraintSplit SketchConstraintCoincidence SketchConstraintMirror SketchConstraintAngle SketchMultiRotation SketchMultiTranslation SketchConstraintCollinear SketchConstraintMiddle"
when_nested="accept abort"
title="Sketch"
tooltip="Create sketch"
</doublevalue>
<validator id="PartSet_FilletSelection"/>
</feature>
+ <!-- SketchConstraintSplit -->
+ <feature id="SketchConstraintSplit" title="Split" tooltip="Create constraints defining split of linear segment, arc or circle" icon="icons/Sketch/split.png">
+ <sketch_shape_selector
+ id="ConstraintEntityA"
+ label="Split feature"
+ tooltip="Select feature for split"
+ shape_types="edge"
+ use_external="false">
+ <validator id="SketchPlugin_SplitValidator"/>
+ </sketch_shape_selector>
+ </feature>
</group>
<group id="Projection">
SET(PROJECT_LIBRARIES
Config
ModelAPI
+ ModelGeomAlgo
GeomAPI
GeomDataAPI
Events
${PROJECT_SOURCE_DIR}/src/Config
${PROJECT_SOURCE_DIR}/src/Events
${PROJECT_SOURCE_DIR}/src/ModelAPI
+ ${PROJECT_SOURCE_DIR}/src/ModelGeomAlgo
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/GeomDataAPI
${PROJECT_SOURCE_DIR}/src/SketchPlugin
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_Events.h>
+#include <ModelGeomAlgo_Point2D.h>
+
#include <Events_InfoMessage.h>
#include <GeomDataAPI_Point2D.h>
std::shared_ptr<GeomAPI_Pnt2d> getPoint(ModelAPI_Feature* theFeature,
const std::string& theAttribute)
{
- std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
-
- /// essential check as it is called in openGl thread
- if (!theFeature || !theFeature->data().get() || !theFeature->data()->isValid())
- return std::shared_ptr<GeomAPI_Pnt2d>();
-
- FeaturePtr aFeature;
- std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
- ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
- if(!anAttr.get()) {
- return std::shared_ptr<GeomAPI_Pnt2d>();
- }
- aFeature = ModelAPI_Feature::feature(anAttr->object());
-
- if (aFeature && aFeature->getKind() == SketchPlugin_Point::ID())
- aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aFeature->data()->attribute(SketchPlugin_Point::COORD_ID()));
-
- else if (anAttr->attr()) {
- aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
- }
+ std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = ModelGeomAlgo_Point2D::getPointOfRefAttr(
+ theFeature, theAttribute, SketchPlugin_Point::ID(), SketchPlugin_Point::COORD_ID());
if (aPointAttr.get() != NULL)
return aPointAttr->pnt();
return std::shared_ptr<GeomAPI_Pnt2d>();
return myWorkshop->operationMgr()->canStartOperation(theId);
}
-void XGUI_ModuleConnector::processLaunchOperation(ModuleBase_Operation* theOperation,
- const bool isUpdatePropertyPanel)
+void XGUI_ModuleConnector::processLaunchOperation(ModuleBase_Operation* theOperation)
{
XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr();
if (anOperationMgr->startOperation(theOperation)) {
- if (isUpdatePropertyPanel) {
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
- if (aFOperation) {
- workshop()->propertyPanel()->updateContentWidget(aFOperation->feature());
- workshop()->propertyPanel()->createContentPanel(aFOperation->feature());
- }
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
+ if (aFOperation) {
+ workshop()->propertyPanel()->updateContentWidget(aFOperation->feature());
+ workshop()->propertyPanel()->createContentPanel(aFOperation->feature());
}
if (!theOperation->getDescription()->hasXmlRepresentation()) {
if (theOperation->commit())
//! Performs the operation launch
//! \param theOperation an operation to be launched
- virtual void processLaunchOperation(ModuleBase_Operation* theOperation,
- const bool isUpdatePropertyPanel);
+ virtual void processLaunchOperation(ModuleBase_Operation* theOperation);
//! Returns started operation by the operation identifier. The operation manager is called.
//! \param theId an operation id
qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
#endif
- ModuleBase_IModule* aModule = myWorkshop->module();
- if (aModule)
- aModule->beforeOperationStarted(aFOperation);
}
}
{
ModuleBase_Operation* aSenderOperation = dynamic_cast<ModuleBase_Operation*>(sender());
updateApplyOfOperations(aSenderOperation);
- emit operationStarted(aSenderOperation);
+ XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+ aWorkshop->operationStarted(aSenderOperation);
}
void XGUI_OperationMgr::onBeforeOperationAborted()
bool abortAllOperations();
signals:
- /// Signal about an operation is started. It is emitted after the start() of operation is done.
- void operationStarted(ModuleBase_Operation* theOperation);
-
/// Signal about an operation is stopped. It is emitted after the stop() of operation is done.
/// \param theOperation a stopped operation
void operationStopped(ModuleBase_Operation* theOperation);
myErrorMgr = new XGUI_ErrorMgr(this, aWorkshop);
- connect(myOperationMgr, SIGNAL(operationStarted(ModuleBase_Operation*)),
- SLOT(onOperationStarted(ModuleBase_Operation*)));
connect(myOperationMgr, SIGNAL(operationResumed(ModuleBase_Operation*)),
SLOT(onOperationResumed(ModuleBase_Operation*)));
connect(myOperationMgr, SIGNAL(operationStopped(ModuleBase_Operation*)),
return aHasNested;
}
-void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation)
+void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation)
{
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
if (!aFOperation)
}
}
-//******************************************************
-void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation)
-{
- setGrantedFeatures(theOperation);
- myModule->operationStarted(theOperation);
-}
-
//******************************************************
void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
{
setGrantedFeatures(theOperation);
if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel
- setPropertyPanel(theOperation);
+ fillPropertyPanel(theOperation);
connectToPropertyPanel(true);
}
updateCommandStatus();
aFOperation->setGrantedOperationIds(aGrantedIds);
}
-
-/*
- * Saves document with given name.
- */
+//******************************************************
void XGUI_Workshop::saveDocument(const QString& theName, std::list<std::string>& theFileNames)
{
QApplication::restoreOverrideCursor();
QApplication::restoreOverrideCursor();
}
+//******************************************************
bool XGUI_Workshop::abortAllOperations()
{
return myOperationMgr->abortAllOperations();
}
+//******************************************************
+void XGUI_Workshop::operationStarted(ModuleBase_Operation* theOperation)
+{
+ setGrantedFeatures(theOperation);
+ if (!theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel
+ updateCommandStatus();
+ }
+ else {
+ myModule->operationStarted(theOperation);
+ }
+}
+
//******************************************************
void XGUI_Workshop::onOpen()
{
*/
bool abortAllOperations();
+ /// Updates workshop state according to the started operation, e.g. visualizes the property panel
+ /// and connect to it.
+ /// \param theOpertion a started operation
+ void operationStarted(ModuleBase_Operation* theOperation);
+
+
//! Delete features. Delete the referenced features. There can be a question with a list of
//! referenced objects.
//! \param theFeatures a list of objects to be deleted
/// Update the property panel content by the XML description of the operation and set the panel
/// into the operation
/// \param theOperation an operation
- void setPropertyPanel(ModuleBase_Operation* theOperation);
+ void fillPropertyPanel(ModuleBase_Operation* theOperation);
/// Connects or disconnects to the value changed signal of the property panel widgets
/// \param isToConnect a boolean value whether connect or disconnect
/// SLOT, that is called after the operation is started. Update workshop state according to
/// the started operation, e.g. visualizes the property panel and connect to it.
/// \param theOpertion a started operation
- void onOperationStarted(ModuleBase_Operation* theOperation);
+ // void onOperationStarted(ModuleBase_Operation* theOperation);
/// SLOT, that is called after the operation is resumed. Update workshop state according to
/// the started operation, e.g. visualizes the property panel and connect to it.