- // By default, the start point of fillet arc is connected to FeatureA,
- // and the end point - to FeatureB. But when the angle between TangentDirA and
- // TangentDirB greater 180 degree, the sequaence of features need to be reversed.
- double cosBA = aTangentDir[0]->cross(aTangentDir[1]); // cos(B-A), where A and B - angles between corresponding tanget direction and the X axis
- bool isReversed = cosBA > 0.0;
-
- // Calculate fillet arc parameters
- std::shared_ptr<GeomAPI_XY> aCenter, aTangentPntA, aTangentPntB;
- calculateFilletCenter(anOldFeatureA, anOldFeatureB, aFilletRadius, isStart, aCenter, aTangentPntA, aTangentPntB);
- if(!aCenter.get() || !aTangentPntA.get() || !aTangentPntB.get()) {
- setError("Can not create fillet with the specified parameters.");
- return;
- }
- // update features
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aNewFeatureA->attribute(aFeatAttributes[isStart[0] ? 0 : 1]))->setValue(
- aTangentPntA->x(), aTangentPntA->y());
- aNewFeatureA->execute();
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aNewFeatureB->attribute(aFeatAttributes[2 + (isStart[1] ? 0 : 1)]))->setValue(
- aTangentPntB->x(), aTangentPntB->y());
- aNewFeatureB->execute();
- // update fillet arc: make the arc correct for sure, so, it is not needed to process the "attribute updated"
- // by arc; moreover, it may cause cyclicity in hte mechanism of updater
- aNewArc->data()->blockSendAttributeUpdated(true);
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aNewArc->attribute(SketchPlugin_Arc::CENTER_ID()))->setValue(
- aCenter->x(), aCenter->y());
- if (isReversed) {
- std::shared_ptr<GeomAPI_XY> aTmp = aTangentPntA;
- aTangentPntA = aTangentPntB;
- aTangentPntB = aTmp;
- }
- std::shared_ptr<GeomDataAPI_Point2D> aStartPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aNewArc->attribute(SketchPlugin_Arc::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- aNewArc->attribute(SketchPlugin_Arc::END_ID()));
- if (aStartPoint->isInitialized() && aEndPoint->isInitialized() &&
- (aStartPoint->pnt()->xy()->distance(aTangentPntA) > aTol ||
- aEndPoint->pnt()->xy()->distance(aTangentPntB) > aTol))
- std::dynamic_pointer_cast<SketchPlugin_Arc>(aNewArc)->setReversed(false);
- aStartPoint->setValue(aTangentPntA->x(), aTangentPntA->y());
- aEndPoint->setValue(aTangentPntB->x(), aTangentPntB->y());
- aNewArc->data()->blockSendAttributeUpdated(false);
- aNewArc->execute();
-
- if (needNewObjects) {
- // attach new arc to the list
- aRefListOfFillet->append(aNewFeatureA->lastResult());
- aRefListOfFillet->append(aNewFeatureB->lastResult());
- aRefListOfFillet->append(aNewArc->lastResult());
-
- myProducedFeatures.push_back(aNewFeatureA);
- myProducedFeatures.push_back(aNewFeatureB);
- myProducedFeatures.push_back(aNewArc);
-
- // Create list of additional constraints:
- // 1. Coincidence of boundary points of features (copied lines/arcs) and fillet arc
- // 1.1. coincidence
- FeaturePtr aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- aRefAttr->setAttr(aNewArc->attribute(SketchPlugin_Arc::START_ID()));
- aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
- int aFeatInd = isReversed ? 1 : 0;
- int anAttrInd = (isReversed ? 2 : 0) + (isStart[isReversed ? 1 : 0] ? 0 : 1);
- aRefAttr->setAttr(aNewFeature[aFeatInd]->attribute(aFeatAttributes[anAttrInd]));
- recalculateAttributes(aNewArc, SketchPlugin_Arc::START_ID(), aNewFeature[aFeatInd], aFeatAttributes[anAttrInd]);
- aConstraint->execute();
- myProducedFeatures.push_back(aConstraint);
- ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
- // 1.2. coincidence
- aConstraint = sketch()->addFeature(SketchPlugin_ConstraintCoincidence::ID());
- aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- aRefAttr->setAttr(aNewArc->attribute(SketchPlugin_Arc::END_ID()));
- aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
- aFeatInd = isReversed ? 0 : 1;
- anAttrInd = (isReversed ? 0 : 2) + (isStart[isReversed ? 0 : 1] ? 0 : 1);
- aRefAttr->setAttr(aNewFeature[aFeatInd]->attribute(aFeatAttributes[anAttrInd]));
- recalculateAttributes(aNewArc, SketchPlugin_Arc::END_ID(), aNewFeature[aFeatInd], aFeatAttributes[anAttrInd]);
- aConstraint->execute();
- myProducedFeatures.push_back(aConstraint);
- ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
- // 2. Fillet arc radius
- //aConstraint = sketch()->addFeature(SketchPlugin_ConstraintRadius::ID());
- //aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- // aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- //aRefAttr->setObject(aNewArc->lastResult());
- //std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- // aConstraint->attribute(SketchPlugin_Constraint::VALUE()))->setValue(aFilletRadius);
- //std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- // aConstraint->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()))->setValue(
- // isStart[0] ? aStartEndPnt[0] : aStartEndPnt[1]);
- //aConstraint->execute();
- //myProducedFeatures.push_back(aConstraint);
- //ModelAPI_EventCreator::get()->sendUpdated(aConstraint, anUpdateEvent);
- // 3. Tangency of fillet arc and features