return aPath;
}
+bool Model_Document::isRoot() const
+{
+ return this == Model_Session::get()->moduleDocument().get();
+}
+
bool Model_Document::load(const char* theFileName)
{
Handle(Model_Application) anApp = Model_Application::getApplication();
- if (this == Model_Session::get()->moduleDocument().get()) {
+ if (isRoot()) {
anApp->setLoadPath(theFileName);
}
TCollection_ExtendedString aPath(DocFileName(theFileName, myID));
std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
aSession->setActiveDocument(anApp->getDocument(myID), false);
aSession->setCheckTransactions(false);
- synchronizeFeatures(false, true);
+ synchronizeFeatures(false, true, true);
aSession->setCheckTransactions(true);
aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
aSession->setActiveDocument(anApp->getDocument(myID), true);
{
// create a directory in the root document if it is not yet exist
Handle(Model_Application) anApp = Model_Application::getApplication();
- if (this == Model_Session::get()->moduleDocument().get()) {
+ if (isRoot()) {
#ifdef WIN32
CreateDirectory(theFileName, NULL);
#else
void Model_Document::close(const bool theForever)
{
std::shared_ptr<ModelAPI_Session> aPM = Model_Session::get();
- if (this != aPM->moduleDocument().get() && this == aPM->activeDocument().get()) {
+ if (!isRoot() && this == aPM->activeDocument().get()) {
aPM->setActiveDocument(aPM->moduleDocument());
- } else if (this == aPM->moduleDocument().get()) {
+ } else if (isRoot()) {
// erase the active document if root is closed
aPM->setActiveDocument(DocumentPtr());
}
// this must be here just after everything is finished but before real transaction stop
// to avoid messages about modifications outside of the transaction
// and to rebuild everything after all updates and creates
- if (Model_Session::get()->moduleDocument().get() == this) { // once for root document
+ if (isRoot()) { // once for root document
Events_Loop::loop()->autoFlush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
static std::shared_ptr<Events_Message> aFinishMsg
(new Events_Message(Events_Loop::eventByName("FinishOperation")));
if (!aResult && !myTransactions.empty() /* it can be for just created part document */)
aResult = myTransactions.rbegin()->myOCAFNum != 0;
- if (!aResult && Model_Session::get()->moduleDocument().get() == this) {
+ if (!aResult && isRoot()) {
// nothing inside in all documents, so remove this transaction from the transactions list
undoInternal(true, false);
myDoc->ClearRedos();
myDoc->Undo();
myDoc->ClearRedos();
}
- synchronizeFeatures(true, false); // references were not changed since transaction start
+ // references were not changed since transaction start
+ synchronizeFeatures(true, false, isRoot());
// abort for all subs
const std::set<std::string> aSubs = subDocuments(true);
std::set<std::string>::iterator aSubIter = aSubs.begin();
for(int a = 0; a < aNumTransactions; a++)
myDoc->Undo();
- if (theSynchronize)
- synchronizeFeatures(true, true);
if (theWithSubs) {
// undo for all subs
const std::set<std::string> aSubs = subDocuments(true);
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize);
}
+ // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
+ if (theSynchronize)
+ synchronizeFeatures(true, true, isRoot());
}
void Model_Document::undo()
for(int a = 0; a < aNumRedos; a++)
myDoc->Redo();
- synchronizeFeatures(true, true);
// redo for all subs
const std::set<std::string> aSubs = subDocuments(true);
std::set<std::string>::iterator aSubIter = aSubs.begin();
for (; aSubIter != aSubs.end(); aSubIter++)
subDoc(*aSubIter)->redo();
+
+ // after redo of all sub-documents to avoid updates on not-modified data (issue 370)
+ synchronizeFeatures(true, true, isRoot());
}
std::list<std::string> Model_Document::undoList() const
theObj->initAttributes();
}
-void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences)
+void Model_Document::synchronizeFeatures(
+ const bool theMarkUpdated, const bool theUpdateReferences, const bool theFlush)
{
std::shared_ptr<ModelAPI_Document> aThis =
Model_Application::getApplication()->getDocument(myID);
myExecuteFeatures = false;
aLoop->activateFlushes(true);
- aLoop->flush(aCreateEvent);
- aLoop->flush(aDeleteEvent);
- aLoop->flush(anUpdateEvent);
- aLoop->flush(aRedispEvent);
- aLoop->flush(aToHideEvent);
+ if (theFlush) {
+ aLoop->flush(aCreateEvent);
+ aLoop->flush(aDeleteEvent);
+ aLoop->flush(anUpdateEvent);
+ aLoop->flush(aRedispEvent);
+ aLoop->flush(aToHideEvent);
+ }
myExecuteFeatures = true;
}
//! Synchronizes myFeatures list with the updated document
//! \param theMarkUpdated causes the "update" event for all features
//! \param theUpdateReferences causes the update of back-references
- void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences);
+ //! \param theFlush makes flush all events in the end of all modifications of this method
+ void synchronizeFeatures(const bool theMarkUpdated, const bool theUpdateReferences,
+ const bool theFlush);
//! Synchronizes the BackReferences list in Data of Features and Results
void synchronizeBackRefs();
/// Internally makes document know that feature was removed or added in history after creation
MODEL_EXPORT virtual void addToHistory(const std::shared_ptr<ModelAPI_Object> theObject);
+ /// Returns true if the document is root module document
+ bool isRoot() const;
+
friend class Model_Application;
friend class Model_Session;
friend class Model_Update;
if (aDoc.get()) {
bool aWasChecked = myCheckTransactions;
setCheckTransactions(false);
- aDoc->synchronizeFeatures(false, true);
+ aDoc->synchronizeFeatures(false, true, true);
if (aWasChecked)
setCheckTransactions(true);
}
aRT->SetRelocation(aSourceRoot, aTargetRoot);
TDF_CopyTool::Copy(aDS, aRT);
- aNew->synchronizeFeatures(false, true);
+ aNew->synchronizeFeatures(false, true, true);
return aNew;
}
Slvs_hParam v = changeParameter(y, aParamIter);
Slvs_Entity aPoint = Slvs_MakePoint2d(++myEntityMaxID, myID, myWorkplane.h, u, v);
myEntities.push_back(aPoint);
+ myEntOfConstr.push_back(true);
aBothMiddlePoints[i] = aPoint.h;
// additional constraint point-on-curve
Slvs_Constraint aPonCircConstr = Slvs_MakeConstraint(
aPoint.h, SLVS_E_UNKNOWN, aBothArcs[i], SLVS_E_UNKNOWN);
myConstraints.push_back(aPonCircConstr);
myConstraintMap[theConstraint].push_back(aPonCircConstr.h);
+ aNewConstraints.push_back(aPonCircConstr.h);
}
aBaseArcPoints[2] = aBothMiddlePoints[0];
std::dynamic_pointer_cast<ModelAPI_Feature>(*aBaseIter);
if (!aBaseFeature) continue;
std::list<AttributePtr> aPoints = aBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::iterator anIt = aPoints.begin();
- for ( ; anIt != aPoints.end(); anIt++) {
+ if (aBaseFeature->getKind() != SketchPlugin_Arc::ID()) {
+ std::list<AttributePtr>::iterator anIt = aPoints.begin();
+ for ( ; anIt != aPoints.end(); anIt++) {
+ addTemporaryConstraintWhereDragged(*anIt);
+ }
+ } else {
// Arcs are fixed by center and start points only (to avoid solving errors in SolveSpace)
- if (aBaseFeature->getKind() == SketchPlugin_Arc::ID() &&
- (*anIt)->id() == SketchPlugin_Arc::END_ID())
- continue;
- addTemporaryConstraintWhereDragged(*anIt);
+ AttributePtr aCenterAttr = aBaseFeature->attribute(SketchPlugin_Arc::CENTER_ID());
+ std::map<AttributePtr, Slvs_hEntity>::iterator aFound = myEntityAttrMap.find(aCenterAttr);
+ Slvs_hEntity anArcPoints[3] = {aFound->second, 0, 0};
+ AttributePtr aStartAttr = aBaseFeature->attribute(SketchPlugin_Arc::START_ID());
+ aFound = myEntityAttrMap.find(aStartAttr);
+ anArcPoints[1] = aFound->second;
+ AttributePtr aEndAttr = aBaseFeature->attribute(SketchPlugin_Arc::END_ID());
+ aFound = myEntityAttrMap.find(aEndAttr);
+ anArcPoints[2] = aFound->second;
+
+ bool isFixed[3] = {false, false, false};
+ int aNbFixed = 0; // number of already fixed points on the arc
+ for (int i = 0; i < 3; i++) {
+ std::vector<std::set<Slvs_hEntity> >::iterator aCoPtIter = myCoincidentPoints.begin();
+ for (; aCoPtIter != myCoincidentPoints.end() && !isFixed[i]; aCoPtIter++) {
+ if (aCoPtIter->find(anArcPoints[i]) == aCoPtIter->end())
+ continue; // the entity was not found in current set
+
+ // Find one of already created SLVS_C_WHERE_DRAGGED constraints in current set of coincident points
+ std::vector<Slvs_Constraint>::iterator aConstrIter = myConstraints.begin();
+ for (; aConstrIter != myConstraints.end(); aConstrIter++)
+ if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
+ aCoPtIter->find(aConstrIter->ptA) != aCoPtIter->end()) {
+ isFixed[i] = true;
+ aNbFixed++;
+ break; // the SLVS_C_WHERE_DRAGGED constraint already exists
+ }
+ }
+ }
+ if (aNbFixed < 2) { // append constraints
+ if (!isFixed[0])
+ addTemporaryConstraintWhereDragged(aCenterAttr);
+ if (!isFixed[1] && (isFixed[0] || aNbFixed == 0))
+ addTemporaryConstraintWhereDragged(aStartAttr);
+ }
}
}
}
Slvs_Entity aBase = myEntities[Search(theBase, myEntities)];
Slvs_Entity aMirror = myEntities[Search(theMirror, myEntities)];
int i = 0;
- while (aBase.point[i] != 0 && aMirror.point[i] != 0) {
- makeMirrorEntity(aBase.point[i], aMirror.point[i], theMirrorLine);
- i++;
+ if (aBase.type != SLVS_E_ARC_OF_CIRCLE) {
+ while (aBase.point[i] != 0 && aMirror.point[i] != 0) {
+ makeMirrorEntity(aBase.point[i], aMirror.point[i], theMirrorLine);
+ i++;
+ }
+ } else {
+ // swap mirroring first and last points of an arc
+ makeMirrorEntity(aBase.point[0], aMirror.point[0], theMirrorLine);
+ makeMirrorEntity(aBase.point[1], aMirror.point[2], theMirrorLine);
+ makeMirrorEntity(aBase.point[2], aMirror.point[1], theMirrorLine);
}
if (aBase.param[0] != 0 && aMirror.param[0] != 0) { // this is a point, copy it
Slvs_Entity aMirrorLine = myEntities[Search(theMirrorLine, myEntities)];
for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
std::shared_ptr<SketchPlugin_Feature> aFeature =
std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (!aFeature || aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+ if (!aFeature /*|| aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()*/)
continue;
changeConstraintOrEntity(aFeature);
}