From: szy Date: Fri, 31 Oct 2014 08:33:22 +0000 (+0300) Subject: Merge branch 'master' of newgeom:newgeom X-Git-Tag: V_0.5~48^2~9 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=8c99e5e8dd74d99dfbf534bd66b32b70ca134aa7;hp=393cfb1948498b0adb2d10a25a6cc9e5b7dc7e59;p=modules%2Fshaper.git Merge branch 'master' of newgeom:newgeom --- diff --git a/env_Salome.bat b/env_Salome.bat index 98d24b244..ffad9939b 100644 --- a/env_Salome.bat +++ b/env_Salome.bat @@ -75,6 +75,7 @@ rem @SET PATH=%SOLVESPACE_ROOT_DIR%\lib;%PATH% @SET PATH=%GEOM_ROOT_DIR%\lib\salome;%PATH% +@SET _NO_DEBUG_HEAP=1 IF "%ARCH%" == "Win64" ( call "%VS100COMNTOOLS%..\..\VC\vcvarsall.bat" x64 diff --git a/src/FeaturesPlugin/FeaturesPlugin_Group.cpp b/src/FeaturesPlugin/FeaturesPlugin_Group.cpp index dad22dbf6..e9ae74d59 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Group.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Group.cpp @@ -25,10 +25,7 @@ void FeaturesPlugin_Group::initAttributes() void FeaturesPlugin_Group::execute() { - //AttributeStringPtr aNameAttr = boost::dynamic_pointer_cast( - // data()->attribute(FeaturesPlugin_Group::NAME_ID())); - //if (!aNameAttr) - // return; - //std::string aName = aNameAttr->value(); - //data()->setName(aName); + if (results().empty()) { // just create result if not exists + document()->createGroup(data()); + } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Group.h b/src/FeaturesPlugin/FeaturesPlugin_Group.h index 23078ae67..7138c1241 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Group.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Group.h @@ -44,6 +44,9 @@ class FeaturesPlugin_Group : public ModelAPI_Feature /// Request for initialization of data model of the feature: adding all attributes FEATURESPLUGIN_EXPORT virtual void initAttributes(); + /// Result of groups is created on the fly and don't stored to the document + FEATURESPLUGIN_EXPORT virtual bool isPersistentResult() {return false;} + /// Use plugin manager for features creation FeaturesPlugin_Group(); diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index 1656a618f..753fd7817 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -22,6 +22,7 @@ SET(PROJECT_HEADERS Model_ResultBody.h Model_ResultConstruction.h Model_ResultPart.h + Model_ResultGroup.h Model_FeatureValidator.h ) @@ -46,6 +47,7 @@ SET(PROJECT_SOURCES Model_ResultBody.cpp Model_ResultConstruction.cpp Model_ResultPart.cpp + Model_ResultGroup.cpp Model_FeatureValidator.cpp ) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index f502aee03..dd360d258 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,8 +29,20 @@ #include #include #include +#include +#include using namespace std; +/// adeed to the index in the packed map to signalize that the vertex of edge is seleted +/// (multiplied by the index of the edge) +static const int kSTART_VERTEX_DELTA = 1000000; + +// on this label is stored: +// TNaming_NamedShape - selected shape +// TNaming_Naming - topological selection information (for the body) +// TDataStd_IntPackedMap - indexes of edges in composite element (for construction) +// TDataStd_Integer - type of the selected shape (for construction) +// TDF_Reference - from ReferenceAttribute, the context void Model_AttributeSelection::setValue(const ResultPtr& theContext, const boost::shared_ptr& theSubShape) @@ -91,88 +104,167 @@ bool Model_AttributeSelection::update() // body: just a named shape, use selection mechanism from OCCT TNaming_Selector aSelector(selectionLabel()); TDF_LabelMap aScope; // empty means the whole document + owner()->data()->sendAttributeUpdated(this); return aSelector.Solve(aScope) == Standard_True; - } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { // construction: identification by the results indexes, recompute faces and // take the face that more close by the indexes - boost::shared_ptr aWirePtr = boost::dynamic_pointer_cast( + boost::shared_ptr aWirePtr = + boost::dynamic_pointer_cast( boost::dynamic_pointer_cast(aContext)->shape()); if (aWirePtr && aWirePtr->hasPlane()) { - // If this is a wire with plane defined thin it is a sketch-like object - std::list > aFaces; - GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(), - aWirePtr->dirY(), aWirePtr->norm(), aWirePtr, aFaces); - if (aFaces.empty()) // no faces, update can not work correctly - return false; - // if there is no edges indexes, any face can be used: take the first boost::shared_ptr aData = boost::dynamic_pointer_cast(owner()->data()); TDF_Label aLab = aData->label(); + // getting a type of selected shape + Handle(TDataStd_Integer) aTypeAttr; + if (!aLab.FindAttribute(TDataStd_Integer::GetID(), aTypeAttr)) { + return false; + } + TopAbs_ShapeEnum aShapeType = (TopAbs_ShapeEnum)(aTypeAttr->Get()); + // selected indexes will be needed in each "if" Handle(TDataStd_IntPackedMap) aSubIds; boost::shared_ptr aNewSelected; - if (!aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0) { - aNewSelected = *(aFaces.begin()); - } else { // searching for most looks-like initial face by the indexes - // prepare edges of the current resut for the fast searching - TColStd_MapOfTransient allCurves; - FeaturePtr aContextFeature = owner()->document()->feature(aContext); - CompositeFeaturePtr aComposite = - boost::dynamic_pointer_cast(aContextFeature); - if (!aComposite) // must be composite at least for the current implementation + bool aNoIndexes = + !aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0; + // for now working only with composite features + FeaturePtr aContextFeature = owner()->document()->feature(aContext); + CompositeFeaturePtr aComposite = + boost::dynamic_pointer_cast(aContextFeature); + if (!aComposite || aComposite->numberOfSubs() == 0) { + return false; + } + + if (aShapeType == TopAbs_FACE) { + // If this is a wire with plane defined thin it is a sketch-like object + std::list > aFaces; + GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(), + aWirePtr->dirY(), aWirePtr->norm(), aWirePtr, aFaces); + if (aFaces.empty()) // no faces, update can not work correctly return false; - const int aSubNum = aComposite->numberOfSubs(); - for(int a = 0; a < aSubNum; a++) { - if (aSubIds->Contains(aComposite->subFeatureId(a))) { - FeaturePtr aSub = aComposite->subFeature(a); - const std::list >& aResults = aSub->results(); - std::list >::const_iterator aRes = aResults.cbegin(); - for(; aRes != aResults.cend(); aRes++) { - ResultConstructionPtr aConstr = - boost::dynamic_pointer_cast(*aRes); - if (aConstr->shape() && aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - allCurves.Add(aCurve); + // if there is no edges indexes, any face can be used: take the first + boost::shared_ptr aNewSelected; + if (aNoIndexes) { + aNewSelected = *(aFaces.begin()); + } else { // searching for most looks-like initial face by the indexes + // prepare edges of the current resut for the fast searching + TColStd_MapOfTransient allCurves; + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + if (aSubIds->Contains(aComposite->subFeatureId(a))) { + FeaturePtr aSub = aComposite->subFeature(a); + const std::list >& aResults = aSub->results(); + std::list >::const_iterator aRes; + for(aRes = aResults.cbegin(); aRes != aResults.cend(); aRes++) { + ResultConstructionPtr aConstr = + boost::dynamic_pointer_cast(*aRes); + if (aConstr->shape() && aConstr->shape()->isEdge()) { + const TopoDS_Shape& aResShape = aConstr->shape()->impl(); + TopoDS_Edge anEdge = TopoDS::Edge(aResShape); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + allCurves.Add(aCurve); + } + } + } + } + } + // iterate new result faces and searching for these edges + std::list >::iterator aFacesIter = aFaces.begin(); + double aBestFound = 0; // best percentage of found edges + for(; aFacesIter != aFaces.end(); aFacesIter++) { + int aFound = 0, aNotFound = 0; + TopExp_Explorer anEdgesExp((*aFacesIter)->impl(), TopAbs_EDGE); + for(; anEdgesExp.More(); anEdgesExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current()); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (allCurves.Contains(aCurve)) { + aFound++; + } else { + aNotFound++; } } } + if (aFound + aNotFound != 0) { + double aPercentage = double(aFound) / double(aFound + aNotFound); + if (aPercentage > aBestFound) { + aBestFound = aPercentage; + aNewSelected = *aFacesIter; + } + } } } - // iterate new result faces and searching for these edges - std::list >::iterator aFacesIter = aFaces.begin(); - double aBestFound = 0; // best percentage of found edges - for(; aFacesIter != aFaces.end(); aFacesIter++) { - int aFound = 0, aNotFound = 0; - TopExp_Explorer anEdgesExp((*aFacesIter)->impl(), TopAbs_EDGE); - for(; anEdgesExp.More(); anEdgesExp.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current()); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (allCurves.Contains(aCurve)) { - aFound++; - } else { - aNotFound++; + if (aNewSelected) { // store this new selection + selectConstruction(aContext, aNewSelected); + owner()->data()->sendAttributeUpdated(this); + return true; + } + } else if (aShapeType == TopAbs_EDGE) { + // just reselect the edge by the id + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + // if aSubIds take any, the first appropriate + if (aSubIds->IsEmpty() || aSubIds->Contains(aComposite->subFeatureId(a))) { + // found the appropriate feature + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + boost::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found! + selectConstruction(aContext, aRes->shape()); + owner()->data()->sendAttributeUpdated(this); + return true; } } } - if (aFound + aNotFound != 0) { - double aPercentage = double(aFound) / double(aFound + aNotFound); - if (aPercentage > aBestFound) { - aBestFound = aPercentage; - aNewSelected = *aFacesIter; + } + } else if (aShapeType == TopAbs_VERTEX) { + // just reselect the vertex by the id of edge + const int aSubNum = aComposite->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + // if aSubIds take any, the first appropriate + int aFeatureID = aComposite->subFeatureId(a); + if (aSubIds->IsEmpty() || aSubIds->Contains(aFeatureID)) { + // searching for deltas + int aVertexNum = 0; + if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 1; + else if (aSubIds->Contains(aFeatureID + kSTART_VERTEX_DELTA)) aVertexNum = 2; + // found the feature with appropriate edge + FeaturePtr aFeature = aComposite->subFeature(a); + std::list >::const_iterator aResIter = + aFeature->results().cbegin(); + for(;aResIter != aFeature->results().cend(); aResIter++) { + ResultConstructionPtr aRes = + boost::dynamic_pointer_cast(*aResIter); + if (aRes && aRes->shape()) { + if (aRes->shape()->isVertex() && aVertexNum == 0) { // found! + selectConstruction(aContext, aRes->shape()); + owner()->data()->sendAttributeUpdated(this); + return true; + } else if (aRes->shape()->isEdge() && aVertexNum > 0) { + const TopoDS_Shape& anEdge = aRes->shape()->impl(); + int aVIndex = 1; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + if (aVIndex == aVertexNum) { // found! + boost::shared_ptr aVertex(new GeomAPI_Shape); + aVertex->setImpl(new TopoDS_Shape(aVExp.Current())); + selectConstruction(aContext, aVertex); + owner()->data()->sendAttributeUpdated(this); + return true; + } + aVIndex++; + } + } + } } } } } - if (aNewSelected) { // store this new selection - selectConstruction(aContext, aNewSelected); - return true; - } } } return false; // unknown case @@ -215,12 +307,20 @@ void Model_AttributeSelection::selectConstruction( TDF_Label aLab = aData->label(); // identify the reuslts of sub-object of the composite by edges const TopoDS_Shape& aSubShape = theSubShape->impl(); + // save type of the selected shape in integer attribute + TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType(); + TDataStd_Integer::Set(aLab, (int)aShapeType); + gp_Pnt aVertexPos; TColStd_MapOfTransient allCurves; - for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - allCurves.Add(aCurve); + if (aShapeType == TopAbs_VERTEX) { // compare positions + aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape)); + } else { + for(TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) { + TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current()); + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + allCurves.Add(aCurve); + } } // iterate and store the result ids of sub-elements Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab); @@ -233,17 +333,40 @@ void Model_AttributeSelection::selectConstruction( for(; aRes != aResults.cend(); aRes++) { ResultConstructionPtr aConstr = boost::dynamic_pointer_cast(*aRes); - if (aConstr->shape() && aConstr->shape()->isEdge()) { - const TopoDS_Shape& aResShape = aConstr->shape()->impl(); - TopoDS_Edge anEdge = TopoDS::Edge(aResShape); - if (!anEdge.IsNull()) { - Standard_Real aFirst, aLast; - Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); - if (allCurves.Contains(aCurve)) { - boost::shared_ptr aSubData = boost::dynamic_pointer_cast(aSub->data()); - TDF_Label aSubLab = aSubData->label(); + if (!aConstr->shape()) { + continue; + } + if (aShapeType == TopAbs_VERTEX) { + if (aConstr->shape()->isVertex()) { // compare vertices positions + const TopoDS_Shape& aVertex = aConstr->shape()->impl(); + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex)); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { aRefs->Add(aComposite->subFeatureId(a)); } + } else { // get first or last vertex of the edge: last is stored with negative sign + const TopoDS_Shape& anEdge = aConstr->shape()->impl(); + int aDelta = kSTART_VERTEX_DELTA; + for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) { + gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current())); + if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) { + aRefs->Add(aComposite->subFeatureId(a)); + aRefs->Add(aDelta + aComposite->subFeatureId(a)); + break; + } + aDelta += kSTART_VERTEX_DELTA; + } + } + } else { + if (aConstr->shape()->isEdge()) { + const TopoDS_Shape& aResShape = aConstr->shape()->impl(); + TopoDS_Edge anEdge = TopoDS::Edge(aResShape); + if (!anEdge.IsNull()) { + Standard_Real aFirst, aLast; + Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast); + if (allCurves.Contains(aCurve)) { + aRefs->Add(aComposite->subFeatureId(a)); + } + } } } } diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index cb7158b75..f23e684ca 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -152,13 +152,14 @@ class Model_Data : public ModelAPI_Data /// Returns the identifier of feature-owner, unique in this document MODEL_EXPORT virtual int featureId() const; + // returns all objects referenced to this + MODEL_EXPORT virtual const std::set& refsToMe() {return myRefsToMe;} + private: // removes all information about back references void eraseBackReferences(); // adds a back reference (with identifier which attribute references to this object void addBackReference(FeaturePtr theFeature, std::string theAttrID); - // returns all objects referenced to this - const std::set& refsToMe() {return myRefsToMe;} // returns all references by attributes of this data // \param the returned list of pairs: id of referenced attribute and list of referenced objects void referencesToObjects(std::list > >& theRefs); diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index cb05a7fbb..2487b7c30 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -210,12 +211,12 @@ void Model_Document::close() for (; aSubIter != mySubs.end(); aSubIter++) subDoc(*aSubIter)->close(); mySubs.clear(); - // close this - /* do not close because it can be undoed - if (myDoc->CanClose() == CDM_CCS_OK) - myDoc->Close(); - Model_Application::getApplication()->deleteDocument(myID); - */ + // close this only if it is module document, otherwise it can be undoed + if (this == aPM->moduleDocument().get()) { + if (myDoc->CanClose() == CDM_CCS_OK) + myDoc->Close(); + Model_Application::getApplication()->deleteDocument(myID); + } } void Model_Document::startOperation() @@ -702,29 +703,30 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID()); for (; aLabIter.More(); aLabIter.Next()) { TDF_Label aFeatureLabel = aLabIter.Value()->Label(); + FeaturePtr aFeature; if (!myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted // create a feature - FeaturePtr aNewObj = ModelAPI_Session::get()->createFeature( + aFeature = ModelAPI_Session::get()->createFeature( TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get()) .ToCString()); - if (!aNewObj) { // somethig is wrong, most probably, the opened document has invalid structure + if (!aFeature) { // somethig is wrong, most probably, the opened document has invalid structure Events_Error::send("Invalid type of object in the document"); aLabIter.Value()->Label().ForgetAllAttributes(); continue; } // this must be before "setData" to redo the sketch line correctly - myObjs.Bind(aFeatureLabel, aNewObj); - aNewFeatures.insert(aNewObj); - initData(aNewObj, aFeatureLabel, TAG_FEATURE_ARGUMENTS); + myObjs.Bind(aFeatureLabel, aFeature); + aNewFeatures.insert(aFeature); + initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS); // event: model is updated static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); - ModelAPI_EventCreator::get()->sendUpdated(aNewObj, anEvent); + ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent); // update results of the appeared feature - updateResults(aNewObj); + updateResults(aFeature); } else { // nothing is changed, both iterators are incremented - FeaturePtr aFeature = myObjs.Find(aFeatureLabel); + aFeature = myObjs.Find(aFeatureLabel); aKeptFeatures.insert(aFeature); if (theMarkUpdated) { static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED); @@ -733,11 +735,6 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t updateResults(aFeature); } } - // execute new features to restore results: after features creation to make all references valid - /*std::set::iterator aNewIter = aNewFeatures.begin(); - for(; aNewIter != aNewFeatures.end(); aNewIter++) { - (*aNewIter)->execute(); - }*/ // check all features are checked: if not => it was removed NCollection_DataMap::Iterator aFIter(myObjs); while (aFIter.More()) { @@ -752,14 +749,6 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); const std::list >& aResults = aFeature->results(); std::list >::const_iterator aRIter = aResults.begin(); - /* - for (; aRIter != aResults.cend(); aRIter++) { - boost::shared_ptr aRes = *aRIter; - //aRes->setData(boost::shared_ptr()); // deleted flag - ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP); - ModelAPI_EventCreator::get()->sendDeleted(aThis, aRes->groupName()); - } - */ // redisplay also removed feature (used for sketch and AISObject) ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP); aFeature->erase(); @@ -924,6 +913,23 @@ boost::shared_ptr Model_Document::createPart( return aResult; } +boost::shared_ptr Model_Document::createGroup( + const boost::shared_ptr& theFeatureData, const int theIndex) +{ + TDF_Label aLab = resultLabel(theFeatureData, theIndex); + TDataStd_Comment::Set(aLab, ModelAPI_ResultGroup::group().c_str()); + ObjectPtr anOldObject = object(aLab); + boost::shared_ptr aResult; + if (anOldObject) { + aResult = boost::dynamic_pointer_cast(anOldObject); + } + if (!aResult) { + aResult = boost::shared_ptr(new Model_ResultGroup(theFeatureData)); + storeResult(theFeatureData, aResult, theIndex); + } + return aResult; +} + boost::shared_ptr Model_Document::feature( const boost::shared_ptr& theResult) { @@ -969,7 +975,8 @@ void Model_Document::updateResults(FeaturePtr theFeature) aNewBody = createBody(theFeature->data(), aResIndex); } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) { aNewBody = createPart(theFeature->data(), aResIndex); - } else if (aGroup->Get() != ModelAPI_ResultConstruction::group().c_str()) { + } else if (aGroup->Get() != ModelAPI_ResultConstruction::group().c_str() && + aGroup->Get() != ModelAPI_ResultGroup::group().c_str()) { Events_Error::send(std::string("Unknown type of result is found in the document:") + TCollection_AsciiString(aGroup->Get()).ToCString()); } diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index cbea4a19e..d8743f099 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -121,6 +121,9 @@ class Model_Document : public ModelAPI_Document /// Creates a part results MODEL_EXPORT virtual boost::shared_ptr createPart( const boost::shared_ptr& theFeatureData, const int theIndex = 0); + /// Creates a group results + MODEL_EXPORT virtual boost::shared_ptr createGroup( + const boost::shared_ptr& theFeatureData, const int theIndex = 0); //! Returns a feature by result (owner of result) MODEL_EXPORT virtual boost::shared_ptr diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index ce342c2e9..3c7f7a689 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -101,16 +101,12 @@ boost::shared_ptr Model_ResultBody::shape() return boost::shared_ptr(); } -boost::shared_ptr Model_ResultBody::owner() -{ - return myOwner; -} - void Model_ResultBody::clean() { std::vector::iterator aBuilder = myBuilders.begin(); for(; aBuilder != myBuilders.end(); aBuilder++) delete *aBuilder; + myBuilders.clear(); } Model_ResultBody::~Model_ResultBody() diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index 340b35bb5..a12ccb87d 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -23,7 +23,6 @@ class TNaming_Builder; */ class Model_ResultBody : public ModelAPI_ResultBody { - boost::shared_ptr myOwner; ///< owner of this result /// builders that tores the naming history: one per label to allow store several shapes to one /// label; index in vector corresponds to the label tag std::vector myBuilders; @@ -41,8 +40,6 @@ public: /// Returns the shape-result produced by this feature MODEL_EXPORT virtual boost::shared_ptr shape(); - /// Returns the source feature of this result - MODEL_EXPORT virtual boost::shared_ptr owner(); /// Records the subshape newShape which was generated during a topological construction. /// As an example, consider the case of a face generated in construction of a box. diff --git a/src/Model/Model_ResultGroup.cpp b/src/Model/Model_ResultGroup.cpp new file mode 100644 index 000000000..2fd1ead9d --- /dev/null +++ b/src/Model/Model_ResultGroup.cpp @@ -0,0 +1,34 @@ +// File: Model_ResultGroup.cpp +// Created: 08 Jul 2014 +// Author: Mikhail PONIKAROV + +#include +#include +#include + +Model_ResultGroup::Model_ResultGroup(boost::shared_ptr theOwnerData) +{ + setIsConcealed(false); + myOwnerData = theOwnerData; +} + +boost::shared_ptr Model_ResultGroup::shape() const +{ + boost::shared_ptr aResult; + if (myOwnerData) { + AttributeSelectionListPtr aList = myOwnerData->selectionList("group_list"); + if (aList) { + std::list > aSubs; + for(int a = aList->size(); a >= 0; a--) { + boost::shared_ptr aSelection = aList->value(a)->value(); + if (aSelection && !aSelection->isNull()) { + aSubs.push_back(aSelection); + } + } + if (!aSubs.empty()) { + aResult = GeomAlgoAPI_CompoundBuilder::compound(aSubs); + } + } + } + return aResult; +} diff --git a/src/Model/Model_ResultGroup.h b/src/Model/Model_ResultGroup.h new file mode 100644 index 000000000..30e358898 --- /dev/null +++ b/src/Model/Model_ResultGroup.h @@ -0,0 +1,34 @@ +// File: Model_ResultGroup.h +// Created: 08 Jul 2014 +// Author: Mikhail PONIKAROV + +#ifndef Model_ResultGroup_H_ +#define Model_ResultGroup_H_ + +#include "Model.h" +#include + +/**\class ModelAPI_ResultGroup + * \ingroup DataModel + * \brief The groups result. + * + * Provides a compound of selected elements, without storage, one the fly. + */ +class Model_ResultGroup : public ModelAPI_ResultGroup +{ + boost::shared_ptr myOwnerData; ///< data of owner of this result +public: + /// Returns the compound of selected entities + MODEL_EXPORT virtual boost::shared_ptr shape() const; + + /// Removes the stored builders + MODEL_EXPORT virtual ~Model_ResultGroup() {} + +protected: + /// Makes a body on the given feature data + Model_ResultGroup(boost::shared_ptr theOwnerData); + + friend class Model_Document; +}; + +#endif diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index 0bfa08a58..bbc99cbb1 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -31,6 +31,7 @@ SET(PROJECT_HEADERS ModelAPI_ResultConstruction.h ModelAPI_ResultPart.h ModelAPI_ResultParameters.h + ModelAPI_ResultGroup.h ModelAPI_ResultValidator.h ModelAPI_AttributeValidator.h ModelAPI_Tools.h diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index 2acf4fc6b..191345f1a 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -8,6 +8,7 @@ #include "ModelAPI.h" #include #include +#include #include class ModelAPI_AttributeDocRef; @@ -109,6 +110,9 @@ class MODELAPI_EXPORT ModelAPI_Data /// Returns the identifier of feature-owner, unique in this document virtual int featureId() const = 0; + // returns all objects referenced to this + virtual const std::set >& refsToMe() = 0; + protected: /// Objects are created for features automatically ModelAPI_Data() diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index cdfa1d75e..703ab0f88 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -17,6 +17,7 @@ class ModelAPI_Result; class ModelAPI_ResultConstruction; class ModelAPI_ResultBody; class ModelAPI_ResultPart; +class ModelAPI_ResultGroup; class ModelAPI_Data; /**\class Model_Document @@ -76,6 +77,9 @@ public: /// Creates a part results virtual boost::shared_ptr createPart( const boost::shared_ptr& theFeatureData, const int theIndex = 0) = 0; + /// Creates a group results + virtual boost::shared_ptr createGroup( + const boost::shared_ptr& theFeatureData, const int theIndex = 0) = 0; //! Returns a feature by result (owner of result) virtual boost::shared_ptr feature( diff --git a/src/ModelAPI/ModelAPI_ResultGroup.h b/src/ModelAPI/ModelAPI_ResultGroup.h new file mode 100644 index 000000000..a8b183c12 --- /dev/null +++ b/src/ModelAPI/ModelAPI_ResultGroup.h @@ -0,0 +1,42 @@ +// File: ModelAPI_ResultGroup.hxx +// Created: 07 Jul 2014 +// Author: Mikhail PONIKAROV + +#ifndef ModelAPI_ResultGroup_H_ +#define ModelAPI_ResultGroup_H_ + +#include "ModelAPI_Result.h" +#include +#include +#include + +/**\class ModelAPI_ResultGroup + * \ingroup DataModel + * \brief The groups result. + * + * Provides a compound of selected elements, without storage, one the fly. + */ +class ModelAPI_ResultGroup : public ModelAPI_Result +{ +public: + /// Returns the group identifier of this result + virtual std::string groupName() + { + return group(); + } + + /// Returns the group identifier of this result + static std::string group() + { + static std::string MY_GROUP = "Groups"; + return MY_GROUP; + } + + /// Returns the compound of selected entities + virtual boost::shared_ptr shape() const = 0; +}; + +//! Pointer on feature object +typedef boost::shared_ptr ResultGroupPtr; + +#endif diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index cd728aa7a..a28d62d88 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -29,6 +29,9 @@ #include +#include +#include + #ifdef _DEBUG #include #endif @@ -249,6 +252,7 @@ bool ModuleBase_Operation::activateByPreselection() ModuleBase_ViewerPrs aPrs; QList::const_iterator aWIt; QList::const_iterator aPIt; + bool isSet = false; for (aWIt = aWidgets.constBegin(), aPIt = myPreSelection.constBegin(); (aWIt != aWidgets.constEnd()) && (aPIt != myPreSelection.constEnd()); ++aWIt, ++aPIt) { @@ -256,10 +260,16 @@ bool ModuleBase_Operation::activateByPreselection() aPrs = (*aPIt); ModuleBase_WidgetValueFeature aValue; aValue.setObject(aPrs.object()); - if (!aWgt->setValue(&aValue)) + // Check if the selection has a selected point + // for today it is impossible to do because + // the selected point demands convertation to Sketch plane 2d + if (!aWgt->setValue(&aValue)) { + isSet = false; break; + } else + isSet = true; } - if (canBeCommitted()) { + if (isSet && canBeCommitted()) { // if all widgets are filled with selection commit(); return true; diff --git a/src/NewGeom/NewGeom_DataModel.cpp b/src/NewGeom/NewGeom_DataModel.cpp index 267cb0647..8593ab632 100644 --- a/src/NewGeom/NewGeom_DataModel.cpp +++ b/src/NewGeom/NewGeom_DataModel.cpp @@ -65,6 +65,7 @@ bool NewGeom_DataModel::saveAs(const QString& thePath, CAM_Study* theStudy, QStr bool NewGeom_DataModel::close() { + myModule->workshop()->closeDocument(); return LightApp_DataModel::close(); } diff --git a/src/NewGeom/NewGeom_SalomeViewer.cpp b/src/NewGeom/NewGeom_SalomeViewer.cpp index d9ce85feb..fe9cd2310 100644 --- a/src/NewGeom/NewGeom_SalomeViewer.cpp +++ b/src/NewGeom/NewGeom_SalomeViewer.cpp @@ -48,6 +48,9 @@ void NewGeom_SalomeViewer::setSelector(NewGeom_OCCSelector* theSel) return; else { mySelector->viewer()->getViewManager()->disconnect(this); + OCCViewer_Viewer* aViewer = mySelector->viewer(); + if (aViewer) + aViewer->disconnect(this); } } mySelector = theSel; @@ -123,6 +126,11 @@ void NewGeom_SalomeViewer::onKeyRelease(SUIT_ViewWindow*, QKeyEvent* theEvent) void NewGeom_SalomeViewer::enableSelection(bool isEnabled) { mySelector->viewer()->enableSelection(isEnabled); + // there is a fix for a black-colored window + // the viewer rubber band is valid if the values delta is less than 1 + // TODO: remove this row after moving to SALOME 7.5 + mySelector->viewer()->setInteractionStyle(isEnabled ? SUIT_ViewModel::STANDARD + : SUIT_ViewModel::KEY_FREE); } //********************************************** diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 035444ba9..501105c4f 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -186,6 +186,7 @@ void PartSet_Module::onOperationStopped(ModuleBase_Operation* theOperation) aDisplayer->activate(*anIt, aModes); } aDisplayer->activate(aFeature, aModes); + aDisplayer->clearSelected(); } } }// else { @@ -217,24 +218,6 @@ void PartSet_Module::onMousePressed(QMouseEvent* theEvent) dynamic_cast(workshop()->currentOperation()); if (aPreviewOp) { ModuleBase_ISelection* aSelection = workshop()->selection(); - // Initialise operation with preliminary selection - //QList aSelected = aSelection->getSelected(); - //QList aHighlighted = aSelection->getHighlighted(); - //QList aObjList; - //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier); - //if (aHasShift) { - // foreach(ModuleBase_ViewerPrs aPrs, aSelected) - // aObjList.append(aPrs.object()); - - // foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) { - // if (!aObjList.contains(aPrs.object())) - // aObjList.append(aPrs.object()); - // } - //} else { - // foreach(ModuleBase_ViewerPrs aPrs, aHighlighted) - // aObjList.append(aPrs.object()); - //} - //onSetSelection(aObjList); aPreviewOp->mousePressed(theEvent, myWorkshop->viewer(), aSelection); } } @@ -312,16 +295,16 @@ void PartSet_Module::onRestartOperation(std::string theName, ObjectPtr theObject ModuleBase_ISelection* aSelection = workshop()->selection(); // Initialise operation with preliminary selection aSketchOp->initSelection(aSelection, myWorkshop->viewer()); - } //else if (aFeature) { - //anOperation->setFeature(aFeature); + } else if (aFeature) { // In case of edit operation: set the previously created feature to the operation + anOperation->setFeature(aFeature); ////Deactivate result of current feature in order to avoid its selection - //XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); - //std::list aResults = aFeature->results(); - //std::list::const_iterator aIt; - //for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - // aDisplayer->deactivate(*aIt); - //} - //} + XGUI_Displayer* aDisplayer = xWorkshop()->displayer(); + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { + aDisplayer->deactivate(*aIt); + } + } sendOperation(anOperation); xWorkshop()->actionsMgr()->updateCheckState(); } diff --git a/src/PartSet/PartSet_OperationFeatureEdit.cpp b/src/PartSet/PartSet_OperationFeatureEdit.cpp index a9d85bb8c..517c77cae 100644 --- a/src/PartSet/PartSet_OperationFeatureEdit.cpp +++ b/src/PartSet/PartSet_OperationFeatureEdit.cpp @@ -249,7 +249,7 @@ void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_ // the feature is moved only if there is no a local selection on this feature if (!isMoved) { // MPV: added condition because it could be external edge of some object, not sketch - if (aSketchFeature && aSketchFeature->sketch() == sketch().get()) { + if (aSketchFeature && sketch()->isSub(aSketchFeature)) { aSketchFeature->move(aDeltaX, aDeltaY); static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY); ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent); diff --git a/src/PartSet/PartSet_Tools.cpp b/src/PartSet/PartSet_Tools.cpp index 916a31a71..668cb4653 100644 --- a/src/PartSet/PartSet_Tools.cpp +++ b/src/PartSet/PartSet_Tools.cpp @@ -412,7 +412,14 @@ ResultPtr PartSet_Tools::createFixedObjectByEdge(const ModuleBase_ViewerPrs& the anEdge->setImpl(new TopoDS_Shape(aShape)); anAttr->setValue(aRes, anEdge); + aMyFeature->execute(); + + // fix this edge + FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID()); + aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())-> + setObject(aMyFeature->lastResult()); + return aMyFeature->lastResult(); } } diff --git a/src/PartSetPlugin/PartSetPlugin_Duplicate.h b/src/PartSetPlugin/PartSetPlugin_Duplicate.h index b5e48183f..f327aa7f2 100644 --- a/src/PartSetPlugin/PartSetPlugin_Duplicate.h +++ b/src/PartSetPlugin/PartSetPlugin_Duplicate.h @@ -14,6 +14,13 @@ class PartSetPlugin_Duplicate : public PartSetPlugin_Part { public: + /// Duplicate kind + inline static const std::string& ID() + { + static const std::string MY_DUPLICATE_KIND("Duplicate"); + return MY_DUPLICATE_KIND; + } + /// the reference to copy: reference to the attribute inline static const std::string& ORIGIN_REF() { diff --git a/src/PartSetPlugin/PartSetPlugin_Plugin.cpp b/src/PartSetPlugin/PartSetPlugin_Plugin.cpp index 0ad4b8b92..31c80e495 100644 --- a/src/PartSetPlugin/PartSetPlugin_Plugin.cpp +++ b/src/PartSetPlugin/PartSetPlugin_Plugin.cpp @@ -21,10 +21,10 @@ FeaturePtr PartSetPlugin_Plugin::createFeature(string theFeatureID) if (theFeatureID == PartSetPlugin_Part::ID()) { return FeaturePtr(new PartSetPlugin_Part); } - if (theFeatureID == "duplicate") { + if (theFeatureID == PartSetPlugin_Duplicate::ID()) { return FeaturePtr(new PartSetPlugin_Duplicate); } - if (theFeatureID == "remove") { + if (theFeatureID == PartSetPlugin_Remove::ID()) { return FeaturePtr(new PartSetPlugin_Remove); } // feature of such kind is not found diff --git a/src/PartSetPlugin/plugin-PartSet.xml b/src/PartSetPlugin/plugin-PartSet.xml index 8a9c5ec61..4a846cc42 100644 --- a/src/PartSetPlugin/plugin-PartSet.xml +++ b/src/PartSetPlugin/plugin-PartSet.xml @@ -2,8 +2,8 @@ - - + + diff --git a/src/SketchPlugin/SketchPlugin_Arc.cpp b/src/SketchPlugin/SketchPlugin_Arc.cpp index d9afa4fa9..b2615a6bb 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.cpp +++ b/src/SketchPlugin/SketchPlugin_Arc.cpp @@ -37,68 +37,100 @@ void SketchPlugin_Arc::initAttributes() void SketchPlugin_Arc::execute() { SketchPlugin_Sketch* aSketch = sketch(); - if (aSketch) { - std::list > aShapes; - + // result for the arc is set only when all obligatory attributes are initialized, + // otherwise AIS object is used to visualize the arc's preview + if (aSketch && isFeatureValid()) { // compute a circle point in 3D view boost::shared_ptr aCenterAttr = boost::dynamic_pointer_cast< GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID())); // compute the arc start point boost::shared_ptr aStartAttr = boost::dynamic_pointer_cast< GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID())); - if (aCenterAttr->isInitialized() && aStartAttr->isInitialized()) { - boost::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); - // make a visible point - boost::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); - //aShapes.push_back(aCenterPointShape); - boost::shared_ptr aConstr1 = document()->createConstruction( - data(), 0); - aConstr1->setShape(aCenterPointShape); - aConstr1->setIsInHistory(false); - setResult(aConstr1, 0); - - // make a visible circle - boost::shared_ptr aNDir = boost::dynamic_pointer_cast( - aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); - bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0); - if (aHasPlane) { - boost::shared_ptr aNormal = aNDir->dir(); - boost::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); - - // compute and change the arc end point - boost::shared_ptr anEndAttr = boost::dynamic_pointer_cast< - GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID())); - if (anEndAttr->isInitialized()) { - boost::shared_ptr aCircleForArc( - new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); - boost::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); - if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) - anEndAttr->setValue(aProjection); - } - boost::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); - - boost::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc( - aCenter, aStartPoint, aEndPoint, aNormal); - if (aCircleShape) { - boost::shared_ptr aConstr2 = document()->createConstruction( - data(), 1); - aConstr2->setShape(aCircleShape); - aConstr2->setIsInHistory(false); - setResult(aConstr2, 1); - //aShapes.push_back(aCircleShape); + + boost::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); + // make a visible point + boost::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); + boost::shared_ptr aConstr1 = document()->createConstruction( + data(), 0); + aConstr1->setShape(aCenterPointShape); + aConstr1->setIsInHistory(false); + setResult(aConstr1, 0); + + // make a visible circle + boost::shared_ptr aNDir = boost::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); + bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0); + if (aHasPlane) { + boost::shared_ptr aNormal = aNDir->dir(); + boost::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); + + // compute and change the arc end point + boost::shared_ptr anEndAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID())); + boost::shared_ptr aCircleForArc( + new GeomAPI_Circ2d(aCenterAttr->pnt(), aStartAttr->pnt())); + boost::shared_ptr aProjection = aCircleForArc->project(anEndAttr->pnt()); + if (aProjection && anEndAttr->pnt()->distance(aProjection) > tolerance) + anEndAttr->setValue(aProjection); + boost::shared_ptr aEndPoint(aSketch->to3D(anEndAttr->x(), anEndAttr->y())); + + boost::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc( + aCenter, aStartPoint, aEndPoint, aNormal); + if (aCircleShape) { + boost::shared_ptr aConstr2 = document()->createConstruction( + data(), 1); + aConstr2->setShape(aCircleShape); + aConstr2->setIsInHistory(false); + setResult(aConstr2, 1); + } + } + } +} + +AISObjectPtr SketchPlugin_Arc::getAISObject(AISObjectPtr thePrevious) +{ + SketchPlugin_Sketch* aSketch = sketch(); + if (aSketch) { + // if the feature is valid, the execute() method should be performed, AIS object is empty + if (!isFeatureValid()) { + std::list > aShapes; + + // compute a circle point in 3D view + boost::shared_ptr aCenterAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID())); + if (aCenterAttr->isInitialized()) { + boost::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); + // make a visible point + boost::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); + aShapes.push_back(aCenterPointShape); + + boost::shared_ptr aStartAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID())); + if (aStartAttr->isInitialized()) { + // make a visible circle + boost::shared_ptr aNDir = boost::dynamic_pointer_cast( + aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID())); + bool aHasPlane = aNDir && !(aNDir->x() == 0 && aNDir->y() == 0 && aNDir->z() == 0); + if (aHasPlane) { + boost::shared_ptr aNormal = aNDir->dir(); + boost::shared_ptr aStartPoint(aSketch->to3D(aStartAttr->x(), aStartAttr->y())); + boost::shared_ptr aCircleShape = GeomAlgoAPI_EdgeBuilder::lineCircleArc( + aCenter, aStartPoint, aStartPoint, aNormal); + if (aCircleShape) { + aShapes.push_back(aCircleShape); + } + } } } - /* - boost::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); - // store the result - boost::shared_ptr aConstr = - document()->createConstruction(data()); - aConstr->setShape(aCompound); - aConstr->setIsInHistory(false); - setResult(aConstr); - */ + boost::shared_ptr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aShapes); + AISObjectPtr anAIS = thePrevious; + if (!anAIS) + anAIS = AISObjectPtr(new GeomAPI_AISObject); + anAIS->createShape(aCompound); + return anAIS; } } + return AISObjectPtr(); } void SketchPlugin_Arc::move(double theDeltaX, double theDeltaY) @@ -147,3 +179,15 @@ double SketchPlugin_Arc::distanceToPoint(const boost::shared_ptr& bool SketchPlugin_Arc::isFixed() { return data()->selection(EXTERNAL_ID())->context(); } + +bool SketchPlugin_Arc::isFeatureValid() +{ + boost::shared_ptr aCenterAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::CENTER_ID())); + boost::shared_ptr aStartAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::START_ID())); + boost::shared_ptr anEndAttr = boost::dynamic_pointer_cast< + GeomDataAPI_Point2D>(data()->attribute(SketchPlugin_Arc::END_ID())); + + return aCenterAttr->isInitialized() && aStartAttr->isInitialized() && anEndAttr->isInitialized(); +} diff --git a/src/SketchPlugin/SketchPlugin_Arc.h b/src/SketchPlugin/SketchPlugin_Arc.h index 3ee2ba8e7..a60774336 100644 --- a/src/SketchPlugin/SketchPlugin_Arc.h +++ b/src/SketchPlugin/SketchPlugin_Arc.h @@ -13,8 +13,11 @@ /**\class SketchPlugin_Arc * \ingroup DataModel * \brief Feature for creation of the new arc of circle in PartSet. + * The visualization of this object is separated in two parts. The first one is an AIS object + * calculated when there is non-initialized attributes of the arc. The second is a result and + * it is calculated if all attributes are initialized. */ -class SketchPlugin_Arc : public SketchPlugin_Feature //, public GeomAPI_IPresentable +class SketchPlugin_Arc : public SketchPlugin_Feature, public GeomAPI_IPresentable { public: /// Arc feature kind @@ -60,10 +63,7 @@ class SketchPlugin_Arc : public SketchPlugin_Feature //, public GeomAPI_IPresen SKETCHPLUGIN_EXPORT virtual void initAttributes(); /// Returns the AIS preview - virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious) - { - return simpleAISObject(firstResult(), thePrevious); - } + virtual AISObjectPtr getAISObject(AISObjectPtr thePrevious); /// Moves the feature /// \param theDeltaX the delta for X coordinate is moved @@ -76,6 +76,10 @@ class SketchPlugin_Arc : public SketchPlugin_Feature //, public GeomAPI_IPresen /// Use plugin manager for features creation SketchPlugin_Arc(); + +private: + /// Returns true if all obligatory attributes are initialized + bool isFeatureValid(); }; #endif diff --git a/src/SketchPlugin/SketchPlugin_ConstraintRigid.cpp b/src/SketchPlugin/SketchPlugin_ConstraintRigid.cpp index c9763327e..1b02335df 100644 --- a/src/SketchPlugin/SketchPlugin_ConstraintRigid.cpp +++ b/src/SketchPlugin/SketchPlugin_ConstraintRigid.cpp @@ -6,6 +6,9 @@ #include +#include +#include + SketchPlugin_ConstraintRigid::SketchPlugin_ConstraintRigid() { } @@ -27,16 +30,27 @@ AISObjectPtr SketchPlugin_ConstraintRigid::getAISObject(AISObjectPtr thePrevious boost::shared_ptr aData = data(); boost::shared_ptr anAttr = boost::dynamic_pointer_cast< ModelAPI_AttributeRefAttr>(aData->attribute(SketchPlugin_Constraint::ENTITY_A())); - if (!anAttr || !anAttr->isObject()) - return thePrevious; - - boost::shared_ptr aConst = - boost::dynamic_pointer_cast(anAttr->object()); - if (!aConst) + if (!anAttr /*|| !anAttr->isObject()*/) return thePrevious; boost::shared_ptr aShape; - aShape = aConst->shape(); + + if (anAttr->isObject()) { + boost::shared_ptr aConst; + aConst = boost::dynamic_pointer_cast(anAttr->object()); + + if (!aConst) + return thePrevious; + aShape = aConst->shape(); + } + else { + boost::shared_ptr aPointAttr = + boost::dynamic_pointer_cast(anAttr->attr()); + if (!aPointAttr) + return thePrevious; + boost::shared_ptr aPoint(sketch()->to3D(aPointAttr->x(), aPointAttr->y())); + aShape = GeomAlgoAPI_PointBuilder::point(aPoint); + } AISObjectPtr anAIS = thePrevious; if (!anAIS) diff --git a/src/SketchPlugin/SketchPlugin_Feature.cpp b/src/SketchPlugin/SketchPlugin_Feature.cpp index da25c0999..2d46d8ca1 100644 --- a/src/SketchPlugin/SketchPlugin_Feature.cpp +++ b/src/SketchPlugin/SketchPlugin_Feature.cpp @@ -11,31 +11,23 @@ SketchPlugin_Feature::SketchPlugin_Feature() mySketch = 0; } -/* SketchPlugin_Sketch* SketchPlugin_Feature::sketch() { if (!mySketch) { // find sketch that references to this feature - int aSketches = document()->size(ModelAPI_Feature::group()); - for (int a = 0; a < aSketches && !mySketch; a++) { - ObjectPtr anObj = document()->object(ModelAPI_Feature::group(), a); + const std::set& aBackRefs = data()->refsToMe(); + std::set::const_iterator aBackRef = aBackRefs.begin(); + for(; aBackRef != aBackRefs.end(); aBackRef++) { boost::shared_ptr aSketch = - boost::dynamic_pointer_cast(anObj); + boost::dynamic_pointer_cast((*aBackRef)->owner()); if (aSketch) { - std::list aList = aSketch->data()->reflist(SketchPlugin_Sketch::FEATURES_ID()) - ->list(); - std::list::iterator aSub = aList.begin(); - for (; aSub != aList.end(); aSub++) { - if ((*aSub)->data()->isEqual(data())) { - mySketch = aSketch.get(); - break; - } - } + mySketch = aSketch.get(); + break; } } } return mySketch; -}*/ +} AISObjectPtr SketchPlugin_Feature::simpleAISObject(boost::shared_ptr theRes, AISObjectPtr thePrevious) diff --git a/src/SketchPlugin/SketchPlugin_Feature.h b/src/SketchPlugin/SketchPlugin_Feature.h index 97a2d423b..8c022ed2b 100644 --- a/src/SketchPlugin/SketchPlugin_Feature.h +++ b/src/SketchPlugin/SketchPlugin_Feature.h @@ -56,7 +56,7 @@ class SketchPlugin_Feature : public ModelAPI_Feature SKETCHPLUGIN_EXPORT virtual bool isFixed() {return false;} /// Returns the sketch of this feature - inline SketchPlugin_Sketch* sketch() {return mySketch;} + SketchPlugin_Sketch* sketch(); protected: /// Sets the higher-level feature for the sub-feature (sketch for line) void setSketch(SketchPlugin_Sketch* theSketch) diff --git a/src/SketchPlugin/SketchPlugin_Line.cpp b/src/SketchPlugin/SketchPlugin_Line.cpp index 75c404a77..2d85a43b3 100644 --- a/src/SketchPlugin/SketchPlugin_Line.cpp +++ b/src/SketchPlugin/SketchPlugin_Line.cpp @@ -21,8 +21,7 @@ using namespace std; SketchPlugin_Line::SketchPlugin_Line() : SketchPlugin_Feature() -{ -} +{} void SketchPlugin_Line::initAttributes() { diff --git a/src/SketchPlugin/SketchPlugin_Sketch.cpp b/src/SketchPlugin/SketchPlugin_Sketch.cpp index 42b70c4c6..b5f101595 100644 --- a/src/SketchPlugin/SketchPlugin_Sketch.cpp +++ b/src/SketchPlugin/SketchPlugin_Sketch.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -21,11 +22,15 @@ #include #include #include +#include +#include #include +#include #include +#include #include using namespace std; @@ -41,6 +46,10 @@ void SketchPlugin_Sketch::initAttributes() data()->addAttribute(SketchPlugin_Sketch::DIRY_ID(), GeomDataAPI_Dir::type()); data()->addAttribute(SketchPlugin_Sketch::NORM_ID(), GeomDataAPI_Dir::type()); data()->addAttribute(SketchPlugin_Sketch::FEATURES_ID(), ModelAPI_AttributeRefList::type()); + // the selected face, base for the sketcher plane, not obligatory + data()->addAttribute(SketchPlugin_Feature::EXTERNAL_ID(), ModelAPI_AttributeSelection::type()); + ModelAPI_Session::get()->validators()->registerNotObligatory( + getKind(), SketchPlugin_Feature::EXTERNAL_ID()); } void SketchPlugin_Sketch::execute() @@ -69,6 +78,11 @@ void SketchPlugin_Sketch::execute() for (; anIt != aLast; anIt++) { aFeature = boost::dynamic_pointer_cast(*anIt); if (aFeature) { + // do not include the external edges into the result + if (aFeature->data()->attribute(SketchPlugin_Feature::EXTERNAL_ID())) { + if (aFeature->data()->selection(SketchPlugin_Feature::EXTERNAL_ID())->value()) + continue; + } const std::list >& aRes = aFeature->results(); std::list >::const_iterator aResIter = aRes.cbegin(); @@ -254,3 +268,47 @@ void SketchPlugin_Sketch::erase() } ModelAPI_CompositeFeature::erase(); } + +void SketchPlugin_Sketch::attributeChanged() { + static bool myIsUpdated = false; // to avoid infinitive cycle on attrubtes change + boost::shared_ptr aSelection = + data()->selection(SketchPlugin_Feature::EXTERNAL_ID())->value(); + if (aSelection && !myIsUpdated) { // update arguments due to the selection value + myIsUpdated = true; + // update the sketch plane + boost::shared_ptr aPlane = GeomAlgoAPI_FaceBuilder::plane(aSelection); + if (aPlane) { + double anA, aB, aC, aD; + aPlane->coefficients(anA, aB, aC, aD); + + // calculate attributes of the sketch + boost::shared_ptr aNormDir(new GeomAPI_Dir(anA, aB, aC)); + boost::shared_ptr aCoords = aNormDir->xyz(); + boost::shared_ptr aZero(new GeomAPI_XYZ(0, 0, 0)); + aCoords = aCoords->multiplied(-aD * aCoords->distance(aZero)); + boost::shared_ptr anOrigPnt(new GeomAPI_Pnt(aCoords)); + // X axis is preferable to be dirX on the sketch + static const double tol = 1.e-7; + bool isX = fabs(anA - 1.0) < tol && fabs(aB) < tol && fabs(aC) < tol; + boost::shared_ptr aTempDir( + isX ? new GeomAPI_Dir(0, 1, 0) : new GeomAPI_Dir(1, 0, 0)); + boost::shared_ptr aYDir(new GeomAPI_Dir(aNormDir->cross(aTempDir))); + boost::shared_ptr aXDir(new GeomAPI_Dir(aYDir->cross(aNormDir))); + + boost::shared_ptr anOrigin = boost::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::ORIGIN_ID())); + anOrigin->setValue(anOrigPnt); + boost::shared_ptr aNormal = boost::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::NORM_ID())); + aNormal->setValue(aNormDir); + boost::shared_ptr aDirX = boost::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::DIRX_ID())); + aDirX->setValue(aXDir); + boost::shared_ptr aDirY = boost::dynamic_pointer_cast( + data()->attribute(SketchPlugin_Sketch::DIRY_ID())); + aDirY->setValue(aYDir); + boost::shared_ptr aDir = aPlane->direction(); + } + myIsUpdated = false; + } +} diff --git a/src/SketchPlugin/SketchPlugin_Sketch.h b/src/SketchPlugin/SketchPlugin_Sketch.h index 637bd34a9..6a07b55c9 100644 --- a/src/SketchPlugin/SketchPlugin_Sketch.h +++ b/src/SketchPlugin/SketchPlugin_Sketch.h @@ -135,6 +135,7 @@ class SketchPlugin_Sketch : public ModelAPI_CompositeFeature, public GeomAPI_IPr /// Returns the point projected into the sketch plane boost::shared_ptr to2D(const boost::shared_ptr& thePnt); + SKETCHPLUGIN_EXPORT virtual void attributeChanged(); protected: /// Creates a plane and append it to the list /// \param theX the X normal value diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 9e212a4fa..14deb7083 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -94,11 +94,11 @@ - + - + diff --git a/src/XGUI/XGUI_ActionsMgr.cpp b/src/XGUI/XGUI_ActionsMgr.cpp index 081ab537f..0468a39f7 100644 --- a/src/XGUI/XGUI_ActionsMgr.cpp +++ b/src/XGUI/XGUI_ActionsMgr.cpp @@ -115,9 +115,11 @@ void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& t void XGUI_ActionsMgr::setActionChecked(const QString& theId, const bool theChecked) { - QAction* anAction = myActions[theId]; - if (anAction && anAction->isCheckable()) { - anAction->setChecked(theChecked); + if (myActions.contains(theId)) { + QAction* anAction = myActions[theId]; + if (anAction->isCheckable()) { + anAction->setChecked(theChecked); + } } } @@ -135,8 +137,7 @@ void XGUI_ActionsMgr::updateByDocumentKind() QString aCmdDocKind; if(aCmd) { aCmdDocKind = aCmd->documentKind(); - } - else { + } else { QString aId = eachAction->data().toString(); if (!aId.isEmpty()) { aCmdDocKind = aWorkshop->salomeConnector()->documentKind(aId); @@ -150,9 +151,8 @@ void XGUI_ActionsMgr::updateByDocumentKind() void XGUI_ActionsMgr::setActionEnabled(const QString& theId, const bool theEnabled) { - QAction* anAction = myActions[theId]; - if (anAction) { - anAction->setEnabled(theEnabled); + if (myActions.contains(theId)) { + myActions[theId]->setEnabled(theEnabled); } } diff --git a/src/XGUI/XGUI_DocumentDataModel.cpp b/src/XGUI/XGUI_DocumentDataModel.cpp index 2744d196d..14a8735b1 100644 --- a/src/XGUI/XGUI_DocumentDataModel.cpp +++ b/src/XGUI/XGUI_DocumentDataModel.cpp @@ -42,6 +42,7 @@ XGUI_DocumentDataModel::XGUI_DocumentDataModel(QObject* theParent) XGUI_DocumentDataModel::~XGUI_DocumentDataModel() { clearModelIndexes(); + clearSubModels(); } void XGUI_DocumentDataModel::processEvent(const boost::shared_ptr& theMessage) @@ -80,10 +81,9 @@ void XGUI_DocumentDataModel::processEvent(const boost::shared_ptr::const_iterator aIt; - for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) { - if ((*aIt)->hasDocument(aDoc)) { - aPartModel = (*aIt); + foreach (XGUI_PartModel* aPart, myPartModels) { + if (aPart->hasDocument(aDoc)) { + aPartModel = aPart; break; } } @@ -123,10 +123,9 @@ void XGUI_DocumentDataModel::processEvent(const boost::shared_ptr::const_iterator aIt; - for (aIt = myPartModels.constBegin(); aIt != myPartModels.constEnd(); ++aIt) { - if ((*aIt)->hasDocument(aDoc)) { - aPartModel = (*aIt); + foreach (XGUI_PartModel* aPart, myPartModels) { + if (aPart->hasDocument(aDoc)) { + aPartModel = aPart; break; } } @@ -361,12 +360,18 @@ QModelIndex* XGUI_DocumentDataModel::getModelIndex(const QModelIndex& theIndex) void XGUI_DocumentDataModel::clearModelIndexes() { - QList::const_iterator aIt; - for (aIt = myIndexes.constBegin(); aIt != myIndexes.constEnd(); ++aIt) - delete (*aIt); + foreach (QModelIndex* aIndex, myIndexes) + delete aIndex; myIndexes.clear(); } +void XGUI_DocumentDataModel::clearSubModels() +{ + foreach (XGUI_PartModel* aPart, myPartModels) + delete aPart; + myPartModels.clear(); +} + ObjectPtr XGUI_DocumentDataModel::object(const QModelIndex& theIndex) const { if (theIndex.internalId() == PartsFolder) @@ -570,3 +575,13 @@ QModelIndex XGUI_DocumentDataModel::objectIndex(const ObjectPtr theObject) const } return QModelIndex(); } + + +void XGUI_DocumentDataModel::clear() +{ + clearModelIndexes(); + clearSubModels(); + myActivePart = 0; + myActivePartIndex = QModelIndex(); + myModel->setItemsColor(ACTIVE_COLOR); +} diff --git a/src/XGUI/XGUI_DocumentDataModel.h b/src/XGUI/XGUI_DocumentDataModel.h index c24360827..a7e9fc944 100644 --- a/src/XGUI/XGUI_DocumentDataModel.h +++ b/src/XGUI/XGUI_DocumentDataModel.h @@ -78,6 +78,10 @@ Q_OBJECT void rebuildDataTree(); + //! Clear internal data + void clear(); + + private: enum @@ -98,6 +102,9 @@ Q_OBJECT //! Deletes all saved pointers on QModelIndex objects. void clearModelIndexes(); + //! Deletes all saved pointers on QModelIndex objects. + void clearSubModels(); + //! Removes sub-model on removing a part object. Also it removes QModelIndex-es which refer to this model void removeSubModel(int theModelId); diff --git a/src/XGUI/XGUI_ObjectsBrowser.cpp b/src/XGUI/XGUI_ObjectsBrowser.cpp index 4268115fd..699d6e518 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.cpp +++ b/src/XGUI/XGUI_ObjectsBrowser.cpp @@ -84,6 +84,14 @@ void XGUI_DataTree::commitData(QWidget* theEditor) } } +void XGUI_DataTree::clear() +{ + mySelectedData.clear(); + XGUI_DocumentDataModel* aModel = dataModel(); + aModel->clear(); + reset(); +} + //******************************************************************** //******************************************************************** //******************************************************************** @@ -348,3 +356,11 @@ void XGUI_ObjectsBrowser::processEvent(const boost::shared_ptr& { myDocModel->processEvent(theMessage); } + + +//*************************************************** +void XGUI_ObjectsBrowser::clearContent() +{ + myObjectsList.clear(); + myTreeView->clear(); +} diff --git a/src/XGUI/XGUI_ObjectsBrowser.h b/src/XGUI/XGUI_ObjectsBrowser.h index ebcaffe08..9e7f901d7 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.h +++ b/src/XGUI/XGUI_ObjectsBrowser.h @@ -36,6 +36,9 @@ signals: //! Emited on context menu request void contextMenuRequested(QContextMenuEvent* theEvent); +public slots: + virtual void clear(); + protected slots: virtual void commitData(QWidget* theEditor); @@ -96,6 +99,9 @@ Q_OBJECT void processEvent(const boost::shared_ptr& theMessage); + // Resets the object browser into initial state + void clearContent(); + signals: //! Emited when selection is changed void selectionChanged(); diff --git a/src/XGUI/XGUI_Preferences.cpp b/src/XGUI/XGUI_Preferences.cpp index 4d91ceb34..635462d89 100644 --- a/src/XGUI/XGUI_Preferences.cpp +++ b/src/XGUI/XGUI_Preferences.cpp @@ -270,7 +270,7 @@ void XGUI_PreferencesDlg::modified(XGUI_Prefs& theModified) const void XGUI_PreferencesDlg::onDefault() { // reset main resources -#ifdef WIN32 +#ifdef SALOME_750 // until SALOME 7.5.0 is released QtxResourceMgr::WorkingMode aPrev = myPreferences->resourceMgr()->setWorkingMode(QtxResourceMgr::IgnoreUserValues); myPreferences->retrieve(); diff --git a/src/XGUI/XGUI_RubberBand.cpp b/src/XGUI/XGUI_RubberBand.cpp index 1ed0d5f32..390368256 100644 --- a/src/XGUI/XGUI_RubberBand.cpp +++ b/src/XGUI/XGUI_RubberBand.cpp @@ -137,7 +137,8 @@ void XGUI_AbstractRubberBand::updateMask() if (isClosed()) r += createRegion(myPoints.last(), myPoints.first()); - setMask(r); + if (!r.isEmpty()) + setMask(r); } //********************************************************** diff --git a/src/XGUI/XGUI_ViewWindow.cpp b/src/XGUI/XGUI_ViewWindow.cpp index b64386288..b07d4676a 100644 --- a/src/XGUI/XGUI_ViewWindow.cpp +++ b/src/XGUI/XGUI_ViewWindow.cpp @@ -22,6 +22,8 @@ #include #include +#include + #define BORDER_SIZE 2 const char* imageZoomCursor[] = { "32 32 3 1", ". c None", "a c #000000", "# c #ffffff", diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 22358aab9..1d72cff78 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -1306,3 +1306,15 @@ void XGUI_Workshop::setDisplayMode(const QList& theList, int theMode) if (theList.size() > 0) myDisplayer->updateViewer(); } + +//************************************************************** +void XGUI_Workshop::closeDocument() +{ + myDisplayer->closeLocalContexts(); + myDisplayer->eraseAll(); + objectBrowser()->clearContent(); + + SessionPtr aMgr = ModelAPI_Session::get(); + aMgr->moduleDocument()->close(); + objectBrowser()->clearContent(); +} diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index d5159189a..764e19f2d 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -214,6 +214,8 @@ signals: void activateLastPart(); + void closeDocument(); + protected: bool event(QEvent * theEvent); //Event-loop processing methods: