data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefList::typeId());
+ // This attribute used to store base edges
+ data()->addAttribute(SketchPlugin_Constraint::ENTITY_C(), ModelAPI_AttributeRefList::typeId());
data()->addAttribute(PREVIOUS_VALUE, ModelAPI_AttributeDouble::typeId());
// initialize attribute not applicable for user
ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_B());
+ ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SketchPlugin_Constraint::ENTITY_C());
data()->attribute(PREVIOUS_VALUE)->setInitialized();
std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(PREVIOUS_VALUE))->setValue(0.0);
}
aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
bool needNewObjects = aRefListOfFillet->size() == 0;
+ AttributeRefListPtr aRefListOfBaseLines = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aData->attribute(SketchPlugin_Constraint::ENTITY_C()));
+
// Obtain base features
- AttributePtr anAttrBase = aBaseA->attr();
- const std::set<AttributePtr>& aRefsList = anAttrBase->owner()->data()->refsToMe();
- std::set<AttributePtr>::const_iterator aIt;
- FeaturePtr aCoincident;
- for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
- std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
- FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
- if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
- AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));
- AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
- if(anAttrRefA.get() && !anAttrRefA->isObject()) {
- AttributePtr anAttrA = anAttrRefA->attr();
- if(anAttrBase == anAttrA) {
- aCoincident = aConstrFeature;
- break;
+ FeaturePtr anOldFeatureA, anOldFeatureB;
+ if(needNewObjects) {
+ AttributePtr anAttrBase = aBaseA->attr();
+ const std::set<AttributePtr>& aRefsList = anAttrBase->owner()->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aIt;
+ FeaturePtr aCoincident;
+ for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
+ std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
+ FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
+ if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ AttributeRefAttrPtr anAttrRefA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_A()));
+ AttributeRefAttrPtr anAttrRefB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrFeature->attribute(SketchPlugin_ConstraintCoincidence::ENTITY_B()));
+ if(anAttrRefA.get() && !anAttrRefA->isObject()) {
+ AttributePtr anAttrA = anAttrRefA->attr();
+ if(anAttrBase == anAttrA) {
+ aCoincident = aConstrFeature;
+ break;
+ }
+ }
+ if(anAttrRefA.get() && !anAttrRefB->isObject()) {
+ AttributePtr anAttrB = anAttrRefB->attr();
+ if(anAttrBase == anAttrB) {
+ aCoincident = aConstrFeature;
+ break;
+ }
}
}
- if(anAttrRefA.get() && !anAttrRefB->isObject()) {
- AttributePtr anAttrB = anAttrRefB->attr();
- if(anAttrBase == anAttrB) {
- aCoincident = aConstrFeature;
- break;
+ }
+
+ if(!aCoincident.get()) {
+ setError("No coincident edges at selected vertex");
+ return;
+ }
+
+ std::set<FeaturePtr> aCoinsideLines;
+ SketchPlugin_Tools::findCoincidences(aCoincident,
+ SketchPlugin_ConstraintCoincidence::ENTITY_A(),
+ aCoinsideLines);
+ SketchPlugin_Tools::findCoincidences(aCoincident,
+ SketchPlugin_ConstraintCoincidence::ENTITY_B(),
+ aCoinsideLines);
+
+ // Remove auxilary lines
+ if(aCoinsideLines.size() > 2) {
+ std::set<FeaturePtr> aNewLines;
+ for(std::set<FeaturePtr>::iterator anIt = aCoinsideLines.begin(); anIt != aCoinsideLines.end(); ++anIt) {
+ if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) {
+ aNewLines.insert(*anIt);
}
}
+ aCoinsideLines = aNewLines;
}
- }
- if(!aCoincident.get()) {
- setError("No coincident edges at selected vertex");
- return;
- }
- std::set<FeaturePtr> aCoinsideLines;
- SketchPlugin_Tools::findCoincidences(aCoincident,
- SketchPlugin_ConstraintCoincidence::ENTITY_A(),
- aCoinsideLines);
- SketchPlugin_Tools::findCoincidences(aCoincident,
- SketchPlugin_ConstraintCoincidence::ENTITY_B(),
- aCoinsideLines);
- if(aCoinsideLines.size() != 2) {
- setError("At selected vertex should be two coincident lines");
- return;
- }
+ if(aCoinsideLines.size() != 2) {
+ setError("At selected vertex should be two coincident lines");
+ return;
+ }
- std::set<FeaturePtr>::iterator aLinesIt = aCoinsideLines.begin();
- FeaturePtr anOldFeatureA = *aLinesIt;
- if(!anOldFeatureA) {
- setError("One of the edges is empty");
- return;
+ std::set<FeaturePtr>::iterator aLinesIt = aCoinsideLines.begin();
+ anOldFeatureA = *aLinesIt++;
+ anOldFeatureB = *aLinesIt;
+ } else {
+ std::list<ObjectPtr> aNewFeatList = aRefListOfBaseLines->list();
+ std::list<ObjectPtr>::iterator aFeatIt = aNewFeatList.begin();
+ anOldFeatureA = ModelAPI_Feature::feature(*aFeatIt++);
+ anOldFeatureB = ModelAPI_Feature::feature(*aFeatIt++);
}
- aLinesIt++;
- FeaturePtr anOldFeatureB = *aLinesIt;
- if(!anOldFeatureB) {
+
+ if(!anOldFeatureA.get() || !anOldFeatureB.get()) {
setError("One of the edges is empty");
return;
}
aRefListOfFillet->remove(aNewFeatureA);
aRefListOfFillet->remove(aNewFeatureB);
aRefListOfFillet->remove(aNewArc);
+ aRefListOfBaseLines->clear();
return;
}
aFeatAttributes[2*i] = aStartAttr;
aRefListOfFillet->append(aNewFeatureB->lastResult());
aRefListOfFillet->append(aNewArc->lastResult());
+ // attach base lines to the list
+ aRefListOfBaseLines->append(anOldFeatureA);
+ aRefListOfBaseLines->append(anOldFeatureB);
+
myProducedFeatures.push_back(aNewFeatureA);
myProducedFeatures.push_back(aNewFeatureB);
myProducedFeatures.push_back(aNewArc);
#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeDouble.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketcherPrs_Tools.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_SketchEntity.h>
namespace SketchPlugin_Tools {
}
}
-std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(FeaturePtr theStartCoin)
+std::shared_ptr<GeomAPI_Pnt2d> getCoincidencePoint(const FeaturePtr theStartCoin)
{
std::shared_ptr<GeomAPI_Pnt2d> aPnt = SketcherPrs_Tools::getPoint(theStartCoin.get(),
SketchPlugin_Constraint::ENTITY_A());
return aPnt;
}
-void findCoincidences(FeaturePtr theStartCoin,
- std::string theAttr,
+void findCoincidences(const FeaturePtr theStartCoin,
+ const std::string& theAttr,
std::set<FeaturePtr>& theList)
{
AttributeRefAttrPtr aPnt = theStartCoin->refattr(theAttr);
- if (!aPnt) return;
+ if(!aPnt) {
+ return;
+ }
FeaturePtr aObj = ModelAPI_Feature::feature(aPnt->object());
- if (theList.find(aObj) == theList.end()) {
+ if(theList.find(aObj) == theList.end()) {
std::shared_ptr<GeomAPI_Pnt2d> aOrig = getCoincidencePoint(theStartCoin);
- if (aOrig.get() == NULL)
+ if(aOrig.get() == NULL) {
return;
+ }
theList.insert(aObj);
const std::set<AttributePtr>& aRefsList = aObj->data()->refsToMe();
std::set<AttributePtr>::const_iterator aIt;
- for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
+ for(aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
FeaturePtr aConstrFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
- if (aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
+ if(aConstrFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
std::shared_ptr<GeomAPI_Pnt2d> aPnt = getCoincidencePoint(aConstrFeature);
- if (aPnt.get() && aOrig->isEqual(aPnt)) {
+ if(aPnt.get() && aOrig->isEqual(aPnt)) {
findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_A(), theList);
findCoincidences(aConstrFeature, SketchPlugin_ConstraintCoincidence::ENTITY_B(), theList);
}
}
AttributeRefAttrPtr aBase = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- if (aBase->isObject()) {
+ if(aBase->isObject()) {
return false;
}
+ // If we alredy have some result then all ok
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theAttribute->owner());
+ AttributePtr aBaseLinesAttribute = aFeature->attribute(SketchPlugin_Constraint::ENTITY_C());
+ AttributeRefListPtr aRefListOfBaseLines = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(aBaseLinesAttribute);
+ if(aRefListOfBaseLines->list().size() == 2) {
+ return true;
+ }
+
AttributePtr anAttrBase = aBase->attr();
const std::set<AttributePtr>& aRefsList = anAttrBase->owner()->data()->refsToMe();
std::set<AttributePtr>::const_iterator aIt;
SketchPlugin_Tools::findCoincidences(aCoincident,
SketchPlugin_ConstraintCoincidence::ENTITY_B(),
aCoinsideLines);
+ if(aCoinsideLines.size() < 2) {
+ return false;
+ }
+
+ // Remove auxilary lines
+ if(aCoinsideLines.size() > 2) {
+ std::set<FeaturePtr> aNewLines;
+ for(std::set<FeaturePtr>::iterator anIt = aCoinsideLines.begin(); anIt != aCoinsideLines.end(); ++anIt) {
+ if(!(*anIt)->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) {
+ aNewLines.insert(*anIt);
+ }
+ }
+ aCoinsideLines = aNewLines;
+ }
+
if(aCoinsideLines.size() != 2) {
return false;
}
+ // Check that lines not collinear
+ std::set<FeaturePtr>::iterator anIt = aCoinsideLines.begin();
+ FeaturePtr aFirstFeature = *anIt++;
+ FeaturePtr aSecondFeature = *anIt;
+ if(aFirstFeature->getKind() == SketchPlugin_Line::ID() && aSecondFeature->getKind() == SketchPlugin_Line::ID()) {
+ std::string aStartAttr = SketchPlugin_Line::START_ID();
+ std::string anEndAttr = SketchPlugin_Line::END_ID();
+ std::shared_ptr<GeomAPI_Pnt2d> aFirstStartPnt, aFirstEndPnt, aSecondStartPnt, aSecondEndPnt;
+ aFirstStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aFirstFeature->attribute(aStartAttr))->pnt();
+ aFirstEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aFirstFeature->attribute(anEndAttr))->pnt();
+ aSecondStartPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSecondFeature->attribute(aStartAttr))->pnt();
+ aSecondEndPnt = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aSecondFeature->attribute(anEndAttr))->pnt();
+ double aCheck1 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondStartPnt->y() - aFirstStartPnt->y()) -
+ (aSecondStartPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y()));
+ double aCheck2 = abs((aFirstEndPnt->x() - aFirstStartPnt->x()) * (aSecondEndPnt->y() - aFirstStartPnt->y()) -
+ (aSecondEndPnt->x() - aFirstStartPnt->x()) * (aFirstEndPnt->y() - aFirstStartPnt->y()));
+ if(aCheck1 < 1.e-7 && aCheck2 < 1.e-7) {
+ return false;
+ }
+ }
+
return true;
}