#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
/** \brief Search the entity/parameter with specified ID in the list of elements
* \param[in] theEntityID unique ID of the element
{
}
-bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr& theConstraint)
+bool SolveSpaceSolver_Storage::update(ConstraintWrapperPtr theConstraint)
{
bool isUpdated = false;
std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
for (; anIt != anEntities.end(); ++anIt) {
isUpdated = update(*anIt) || isUpdated;
+ // do not update constrained entities for Multi constraints
+ if (aSlvsConstr.type == SLVS_C_MULTI_ROTATION || aSlvsConstr.type != SLVS_C_MULTI_TRANSLATION)
+ continue;
Slvs_hEntity anID = (Slvs_hEntity)(*anIt)->id();
if ((*anIt)->type() == ENTITY_POINT) {
return isUpdated;
}
-bool SolveSpaceSolver_Storage::update(EntityWrapperPtr& theEntity)
+bool SolveSpaceSolver_Storage::update(EntityWrapperPtr theEntity)
{
bool isUpdated = false;
std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity =
isUpdated = true;
}
}
+ if (theEntity->type() == ENTITY_POINT && aSubEntities.size() == 1) {
+ // theEntity is based on SketchPlugin_Point => need to substitute its attribute instead
+ bool isNew = (aSlvsEnt.h == SLVS_E_UNKNOWN);
+ aSlvsEnt = getEntity(aSlvsEnt.point[0]);
+ if (isNew) {
+ anEntity->changeEntity() = aSlvsEnt;
+ isUpdated = true;
+ }
+ }
// update entity itself
if (aSlvsEnt.wrkpl == SLVS_E_UNKNOWN && myWorkplaneID != SLVS_E_UNKNOWN)
if (aSlvsEnt.group == SLVS_G_UNKNOWN)
aSlvsEnt.group = (Slvs_hGroup)myGroupID;
Slvs_hEntity anEntID = updateEntity(aSlvsEnt);
- if (aSlvsEnt.h == SLVS_E_UNKNOWN) {
+ if (aSlvsEnt.h == SLVS_E_UNKNOWN || isUpdated) {
anEntity->changeEntity() = getEntity(anEntID);
isUpdated = true;
if (anEntity->type() == ENTITY_SKETCH)
storeWorkplane(anEntity);
}
+
return isUpdated;
}
-bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr& theParameter)
+bool SolveSpaceSolver_Storage::update(ParameterWrapperPtr theParameter)
{
std::shared_ptr<SolveSpaceSolver_ParameterWrapper> aParameter =
std::dynamic_pointer_cast<SolveSpaceSolver_ParameterWrapper>(theParameter);
replaceInFeatures(theSlave, theMaster);
replaceInConstraints(theSlave, theMaster);
- // Remove slave entity
- removeEntity((Slvs_hEntity)theSlave->id());
+ // Remove slave entity (if the IDs are equal no need to remove slave entity, just update it)
+ if (theMaster->id() != theSlave->id())
+ removeEntity((Slvs_hEntity)theSlave->id());
std::shared_ptr<SolveSpaceSolver_EntityWrapper> aPointMaster =
std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theMaster);
{
std::map<FeaturePtr, EntityWrapperPtr>::const_iterator anIt = myFeatureMap.begin();
for (; anIt != myFeatureMap.end(); ++anIt) {
+ if (!anIt->second)
+ continue;
bool isUpdated = false;
std::list<EntityWrapperPtr> aSubs = anIt->second->subEntities();
std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
myFixed = theConstraintID;
}
-void SolveSpaceSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
-{
- myTemporaryConstraints.insert(theConstraintID);
-}
-
-void SolveSpaceSolver_Storage::removeAllTemporary()
-{
- myTemporaryConstraints.clear();
-}
-
-size_t SolveSpaceSolver_Storage::removeTemporary(size_t theNbConstraints)
-{
- if (myTemporaryConstraints.empty())
- return 0;
- // Search the point-on-line or a non-rigid constraint
- std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
- for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
- int aPos = Search(*aCIt, myConstraints);
- if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
- break;
- std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
- for (; anIt != myConstraints.end(); anIt++)
- if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
- break;
- if (anIt != myConstraints.end())
- break;
- }
- if (aCIt == myTemporaryConstraints.end())
- aCIt = myTemporaryConstraints.begin();
- bool aNewFixed = false;
-
- size_t aNbRemain = theNbConstraints;
- while (aNbRemain > 0 && aCIt != myTemporaryConstraints.end()) {
- aNewFixed = aNewFixed || (*aCIt == myFixed);
- --aNbRemain;
-
- std::set<Slvs_hConstraint>::iterator aRemoveIt = aCIt++;
- removeConstraint(*aRemoveIt);
- myTemporaryConstraints.erase(aRemoveIt);
- if (aCIt == myTemporaryConstraints.end())
- aCIt = myTemporaryConstraints.begin();
- }
-
- if (aNewFixed) {
- for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
- int aPos = Search(*aCIt, myConstraints);
- if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
- myFixed = *aCIt;
- break;
- }
- }
- }
- return myTemporaryConstraints.size();
-}
-
-bool SolveSpaceSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
-{
- return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
-}
-
-
void SolveSpaceSolver_Storage::initializeSolver(SolverPtr theSolver)
{
Slvs_Constraint aConstraint;
Slvs_hConstraint aConstrID = SLVS_E_UNKNOWN;
bool isFixed = isPointFixed(thePoint.h, aConstrID, true);
- bool isForceUpdate = (isFixed && isTemporary(aConstrID));
+ bool isForceUpdate = (isFixed /*&& isTemporary(aConstrID)*/);
if (!isForceUpdate) { // create new constraint
if (isFixed) return;
aConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, thePoint.group, SLVS_C_WHERE_DRAGGED, thePoint.wrkpl,
return false;
}
-void SolveSpaceSolver_Storage::setTemporary(ConstraintPtr theConstraint)
-{
- // TODO
-}
-bool SolveSpaceSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
+bool SolveSpaceSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
- aFound = myConstraintMap.find(theConstraint);
- if (aFound == myConstraintMap.end())
- return true; // no constraint, already deleted
-
- // Remove constraint
- std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
- myConstraintMap.erase(aFound);
- // Remove SolveSpace constraints
- bool isFullyRemoved = true;
- std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
- while (anIt != aConstrList.end()) {
- if (remove(*anIt)) {
- std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
- aConstrList.erase(aRemoveIt);
- } else {
- isFullyRemoved = false;
- ++anIt;
- }
+ std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
+ std::list<EntityWrapperPtr>::const_iterator aPIt;
+
+ CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
+ for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
+ for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+ if (aPtPtIt->first == *aPIt ||
+ aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
+ break;
+ if (aPIt != aPoints.end())
+ break;
}
- if (!isFullyRemoved)
- myConstraintMap[theConstraint] = aConstrList;
- return isFullyRemoved;
-}
-
-template <class ENT_TYPE>
-static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
-{
- std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
- for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
- if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt)->isBase(theEntity))
- return true;
- return false;
-}
-static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
-{
- std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
- for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
- if (std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*aSubIt)->isBase(theSubEntity))
- return true;
- return false;
-}
+ if (aPtPtIt == myCoincidentPoints.end())
+ return true; // already removed
-bool SolveSpaceSolver_Storage::isUsed(FeaturePtr theFeature) const
-{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt)
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
- if (::isUsed(*aCWIt, theFeature))
- return true;
- // check attributes
- std::list<AttributePtr> anAttrList = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt)
- if (isUsed(*anIt))
- return true;
- return false;
-}
-
-bool SolveSpaceSolver_Storage::isUsed(AttributePtr theAttribute) const
-{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
- else
- anAttribute = aRefAttr->attr();
+ // Create new copies of coincident points
+ BuilderPtr aBuilder = SolveSpaceSolver_Builder::getInstance();
+ std::list<EntityWrapperPtr> aNewPoints;
+ for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
+ aNewPoints.push_back(aBuilder->createAttribute(
+ (*aPIt)->baseAttribute(), myGroupID, myWorkplaneID));
+
+ // Find all points fallen out of group of coincident points
+ std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
+ aNotCoinc[aPtPtIt->first] = EntityWrapperPtr();
+ std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
+ for (; aTempIt != aPtPtIt->second.end(); ++aTempIt)
+ aNotCoinc[*aTempIt] = EntityWrapperPtr();
+ std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
+ aConstrIt = myConstraintMap.begin();
+ for (; aConstrIt != myConstraintMap.end(); ++aConstrIt)
+ if (aConstrIt->first->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr aRefAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefAttrPtr aRefAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrIt->first->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ if (!aRefAttrA || !aRefAttrB || aRefAttrA->isObject() || aRefAttrB->isObject())
+ continue;
+ std::map<AttributePtr, EntityWrapperPtr>::iterator
+ aFound = myAttributeMap.find(aRefAttrA->attr());
+ if (aFound != myAttributeMap.end())
+ aNotCoinc.erase(aFound->second);
+ aFound = myAttributeMap.find(aRefAttrB->attr());
+ if (aFound != myAttributeMap.end())
+ aNotCoinc.erase(aFound->second);
+ }
+ if (aNotCoinc.empty())
+ return false;
+ std::list<EntityWrapperPtr>::const_iterator aNewPIt;
+ for (aPIt = aPoints.begin(), aNewPIt = aNewPoints.begin();
+ aPIt != aPoints.end(); ++aPIt, ++aNewPIt) {
+ if (aNotCoinc.find(*aPIt) != aNotCoinc.end())
+ aNotCoinc[*aPIt] = *aNewPIt;
}
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt)
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
- if (::isUsed(*aCWIt, anAttribute))
- return true;
- return false;
-}
-
-
-bool SolveSpaceSolver_Storage::removeEntity(FeaturePtr theFeature)
-{
- std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
- if (aFound == myFeatureMap.end())
- return false; // feature not found, nothing to delete
-
- // Check the feature is not used by constraints
- if (isUsed(theFeature))
- return false; // the feature is used, don't remove it
-
- // Remove feature
- EntityWrapperPtr anEntity = aFound->second;
- myFeatureMap.erase(aFound);
- if (remove(anEntity))
- return true;
- // feature is not removed, revert operation
- myFeatureMap[theFeature] = anEntity;
- return false;
-}
-
-bool SolveSpaceSolver_Storage::removeEntity(AttributePtr theAttribute)
-{
- std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
- if (aFound == myAttributeMap.end())
- return false; // attribute not found, nothing to delete
-
- // Check the attribute is not used by constraints
- if (isUsed(theAttribute))
- return false; // the attribute is used, don't remove it
- // Check the attribute is not used by other features
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt)
- if (::isUsed(aFIt->second, theAttribute)) // the attribute is used, don't remove it
- return false;
-
- // Remove attribute
- EntityWrapperPtr anEntity = aFound->second;
- myAttributeMap.erase(aFound);
- if (remove(anEntity))
- return true;
- // attribute is not removed, revert operation
- myAttributeMap[theAttribute] = anEntity;
- return false;
+ // Find all features and constraints uses coincident points
+ std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNotCIt;
+ std::set<EntityWrapperPtr> anUpdFeatures;
+ std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
+ for (; aFIt != myFeatureMap.end(); ++aFIt) {
+ for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+ if (!aFIt->second->isUsed(aNotCIt->first->baseAttribute()))
+ continue;
+ std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
+ std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
+ for (; aSIt != aSubs.end(); ++aSIt)
+ if (*aSIt == aNotCIt->first)
+ *aSIt = aNotCIt->second;
+ aFIt->second->setSubEntities(aSubs);
+ anUpdFeatures.insert(aFIt->second);
+ }
+ }
+ // update features
+ std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
+ for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
+ update(EntityWrapperPtr(*anUpdIt));
+
+ // remove not coincident points
+ for (aNotCIt = aNotCoinc.begin(); aNotCIt != aNotCoinc.end(); ++aNotCIt) {
+ if (aPtPtIt->second.size() <= 1) {
+ myCoincidentPoints.erase(aPtPtIt);
+ break;
+ }
+ if (aPtPtIt->first == aNotCIt->first) {
+ std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
+ EntityWrapperPtr aNewMaster = *aSlaves.begin();
+ aSlaves.erase(aSlaves.begin());
+ myCoincidentPoints[aNewMaster] = aSlaves;
+ myCoincidentPoints.erase(aPtPtIt);
+ aPtPtIt = myCoincidentPoints.find(aNewMaster);
+ } else
+ aPtPtIt->second.erase(aNotCIt->first);
+ }
+ return true;
}
-
bool SolveSpaceSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
{
std::shared_ptr<SolveSpaceSolver_ConstraintWrapper> aConstraint =
bool isFullyRemoved = removeConstraint((Slvs_hConstraint)aConstraint->id());
- std::list<EntityWrapperPtr>::const_iterator anIt = aConstraint->entities().begin();
- for (; anIt != aConstraint->entities().end(); ++anIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anIt);
- FeaturePtr aBaseFeature = anEntity->baseFeature();
- if (aBaseFeature)
- isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
- else
- isFullyRemoved = removeEntity(anEntity->baseAttribute()) && isFullyRemoved;
- }
+ // remove point-point coincidence
+ if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
+ isFullyRemoved = removeCoincidence(theConstraint);
- return isFullyRemoved;
+ return SketchSolver_Storage::remove(theConstraint) && isFullyRemoved;
}
bool SolveSpaceSolver_Storage::remove(EntityWrapperPtr theEntity)
{
+ if (!theEntity)
+ return false;
+
std::shared_ptr<SolveSpaceSolver_EntityWrapper> anEntity =
std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(theEntity);
bool isFullyRemoved = removeEntity((Slvs_hEntity)anEntity->id());
-
- std::list<EntityWrapperPtr>::const_iterator anEntIt = anEntity->subEntities().begin();
- for (; anEntIt != anEntity->subEntities().end(); ++anEntIt) {
- std::shared_ptr<SolveSpaceSolver_EntityWrapper> aSubEntity =
- std::dynamic_pointer_cast<SolveSpaceSolver_EntityWrapper>(*anEntIt);
- FeaturePtr aBaseFeature = aSubEntity->baseFeature();
- if (aBaseFeature)
- isFullyRemoved = removeEntity(aBaseFeature) && isFullyRemoved;
- else
- isFullyRemoved = removeEntity(aSubEntity->baseAttribute()) && isFullyRemoved;
- }
-
- std::list<ParameterWrapperPtr>::const_iterator aParIt = anEntity->parameters().begin();
- for (; aParIt != anEntity->parameters().end(); ++aParIt)
- isFullyRemoved = remove(*aParIt) && isFullyRemoved;
- return isFullyRemoved;
+ return SketchSolver_Storage::remove(theEntity) && isFullyRemoved;
}
bool SolveSpaceSolver_Storage::remove(ParameterWrapperPtr theParameter)
void SolveSpaceSolver_Storage::refresh(bool theFixedOnly) const
{
- blockEvents(true);
+ //blockEvents(true);
std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
std::list<ParameterWrapperPtr> aParams;
std::list<ParameterWrapperPtr>::const_iterator aParIt;
for (; anIt != myAttributeMap.end(); ++anIt) {
+ if (!anIt->second)
+ continue;
+ // the external feature always should keep the up to date values, so,
+ // refresh from the solver is never needed
+ if (anIt->first.get()) {
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(anIt->first->owner());
+ if (aSketchFeature.get() && aSketchFeature->isExternal())
+ continue;
+ }
+
// update parameter wrappers and obtain values of attributes
aParams = anIt->second->parameters();
double aCoords[3];
}
}
- blockEvents(false);
+ //blockEvents(false);
}
void SolveSpaceSolver_Storage::verifyFixed()
{
std::map<AttributePtr, EntityWrapperPtr>::iterator anAttrIt = myAttributeMap.begin();
for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
+ if (!anAttrIt->second)
+ continue;
const std::list<ParameterWrapperPtr>& aParameters = anAttrIt->second->parameters();
std::list<ParameterWrapperPtr>::const_iterator aParIt = aParameters.begin();
for (; aParIt != aParameters.end(); ++aParIt)