diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 6edd7e74e3..7963fb3eb7 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1179,85 +1179,16 @@ void SketchObject::addGeometryState(const Constraint* cstr) const { const std::vector< Part::Geometry * > &vals = getInternalGeometry(); - if(cstr->Type == InternalAlignment) { + Sketcher::InternalType::InternalType constraintInternalAlignment = InternalType::None; + bool constraintBlockedState = false; - switch(cstr->AlignmentType){ - case Undef: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::None); - break; - } - case EllipseMajorDiameter: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::EllipseMajorDiameter); - break; - } - case EllipseMinorDiameter: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::EllipseMinorDiameter); - break; - } - case EllipseFocus1: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::EllipseFocus1); - break; - } - case EllipseFocus2: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::EllipseFocus2); - break; - } - case HyperbolaMajor: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::HyperbolaMajor); - break; - } - case HyperbolaMinor: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::HyperbolaMinor); - break; - } - case HyperbolaFocus: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::HyperbolaFocus); - break; - } - case ParabolaFocus: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::ParabolaFocus); - break; - } - case BSplineControlPoint: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::BSplineControlPoint); - - // handle constraint as adimensional - - break; - } - case BSplineKnotPoint: - { - auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setInternalType(InternalType::BSplineKnotPoint); - break; - } - } - } - - // Assign Blocked geometry mode - if(cstr->Type == Block){ + if (getInternalTypeState(cstr, constraintInternalAlignment)) { auto gf = GeometryFacade::getFacade(vals[cstr->First]); - gf->setBlocked(); + gf->setInternalType(constraintInternalAlignment); + } + else if (getBlockedState(cstr, constraintBlockedState)) { + auto gf = GeometryFacade::getFacade(vals[cstr->First]); + gf->setBlocked(constraintBlockedState); } } @@ -7669,9 +7600,93 @@ void SketchObject::onUndoRedoFinished() // such a recompute Constraints.checkConstraintIndices(getHighestCurveIndex(),-getExternalGeometryCount()); // in case it is redoing an operation with invalid data. acceptGeometry(); + synchroniseGeometryState(); solve(); } +void SketchObject::synchroniseGeometryState() +{ + const std::vector< Part::Geometry * > &vals = getInternalGeometry(); + + for(size_t i = 0 ; i < vals.size() ; i++) { + auto gf = GeometryFacade::getFacade(vals[i]); + + auto facadeInternalAlignment = gf->getInternalType(); + auto facadeBlockedState = gf->getBlocked(); + + Sketcher::InternalType::InternalType constraintInternalAlignment = InternalType::None; + bool constraintBlockedState = false; + + for (auto cstr : Constraints.getValues()) { + getInternalTypeState(cstr, constraintInternalAlignment); + getBlockedState(cstr, constraintBlockedState); + } + + if(constraintInternalAlignment != facadeInternalAlignment) + gf->setInternalType(constraintInternalAlignment); + + if(constraintBlockedState != facadeBlockedState) + gf->setBlocked(constraintBlockedState); + + } +} + +bool SketchObject::getInternalTypeState(const Constraint * cstr, Sketcher::InternalType::InternalType & internaltypestate) const +{ + if(cstr->Type == InternalAlignment) { + + switch(cstr->AlignmentType){ + case Undef: + internaltypestate = InternalType::None; + break; + case EllipseMajorDiameter: + internaltypestate = InternalType::EllipseMajorDiameter; + break; + case EllipseMinorDiameter: + internaltypestate = InternalType::EllipseMinorDiameter; + break; + case EllipseFocus1: + internaltypestate = InternalType::EllipseFocus1; + break; + case EllipseFocus2: + internaltypestate = InternalType::EllipseFocus2; + break; + case HyperbolaMajor: + internaltypestate = InternalType::HyperbolaMajor; + break; + case HyperbolaMinor: + internaltypestate = InternalType::HyperbolaMinor; + break; + case HyperbolaFocus: + internaltypestate = InternalType::HyperbolaFocus; + break; + case ParabolaFocus: + internaltypestate = InternalType::ParabolaFocus; + break; + case BSplineControlPoint: + internaltypestate = InternalType::BSplineControlPoint; + break; + case BSplineKnotPoint: + internaltypestate = InternalType::BSplineKnotPoint; + break; + } + + return true; + } + + return false; +} + +bool SketchObject::getBlockedState(const Constraint * cstr, bool & blockedstate) const +{ + if(cstr->Type == Block) { + blockedstate = true; + return true; + } + + return false; +} + void SketchObject::onDocumentRestored() { try { @@ -7690,6 +7705,7 @@ void SketchObject::restoreFinished() validateExternalLinks(); rebuildExternalGeometry(); Constraints.acceptGeometry(getCompleteGeometry()); + synchroniseGeometryState(); // this may happen when saving a sketch directly in edit mode // but never performed a recompute before if (Shape.getValue().IsNull() && hasConflicts() == 0) { diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 0a5957f495..2964af0d2f 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -65,8 +65,8 @@ public: /// Property /** - The Geometry list contains the non-external Part::Geometry objects in the sketch. The list - may be accessed directly, or indirectly via getInternalGeometry(). + The Geometry list contains the non-external Part::Geometry objects in the sketch. The list + may be accessed directly, or indirectly via getInternalGeometry(). Many of the methods in this class take geoId and posId parameters. A GeoId is a unique identifier for geometry in the Sketch. geoId >= 0 means an index in the Geometry list. geoId < 0 refers to sketch @@ -242,7 +242,7 @@ public: \param radius - fillet radius \param trim - if false, leaves the original lines untouched \param createCorner - keep geoId/pos as a Point and keep as many constraints as possible - \retval - 0 on success, -1 on failure + \retval - 0 on success, -1 on failure */ int fillet(int geoId, PointPos pos, double radius, bool trim=true, bool preserveCorner=false); /*! @@ -253,7 +253,7 @@ public: \param trim - if false, leaves the original lines untouched \param preserveCorner - if the lines are coincident, place a Point where they meet and keep as many of the existing constraints as possible - \retval - 0 on success, -1 on failure + \retval - 0 on success, -1 on failure */ int fillet(int geoId1, int geoId2, const Base::Vector3d& refPnt1, const Base::Vector3d& refPnt2, @@ -544,6 +544,18 @@ protected: // retrieves redundant, conflicting and malformed constraint information from the solver void retrieveSolverDiagnostics(); + // retrieves whether a geometry blocked state corresponds to this constraint + // returns true of the constraint is of Block type, false otherwise + bool getBlockedState(const Constraint * cstr, bool & blockedstate) const; + + // retrieves the geometry blocked state corresponding to this constraint + // returns true of the constraint is of InternalAlignment type, false otherwise + bool getInternalTypeState(const Constraint * cstr, Sketcher::InternalType::InternalType & internaltypestate) const; + + // Checks whether the geometry state stored in the geometry extension matches the current sketcher situation (e.g. constraints) + // and corrects the state if not matching. + void synchroniseGeometryState(); + private: /// Flag to allow external geometry from other bodies than the one this sketch belongs to bool allowOtherBody;