+void SketchPlugin_ConstraintSplit::updateTangentConstraintsToFeature(
+ const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theTangentFeatures,
+ const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences)
+{
+ if (theTangentFeatures.empty())
+ return;
+
+ std::map<FeaturePtr, IdToPointPair>::const_iterator aTIt = theTangentFeatures.begin(),
+ aTLast = theTangentFeatures.end();
+#ifdef DEBUG_SPLIT
+ std::cout << std::endl;
+ std::cout << "Tangencies to feature(modified):"<< std::endl;
+#endif
+ for (; aTIt != aTLast; aTIt++) {
+ FeaturePtr aTangentFeature = aTIt->first;
+ std::string anAttributeId = aTIt->second.first;
+ AttributePoint2DPtr aTangentPoint = aTIt->second.second;
+ std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
+ aFCLast = theFurtherCoincidences.end();
+ std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aTangentPoint->pnt();
+ AttributePoint2DPtr aFeaturePointAttribute;
+ /// here we rely on created coincidence between further coincidence point and tangent result
+ for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
+ AttributePoint2DPtr aFCAttribute = *aFCIt;
+ if (aCoincPnt->isEqual(aFCAttribute->pnt()))
+ aFeaturePointAttribute = aFCAttribute;
+ }
+ if (aFeaturePointAttribute.get()) {
+ FeaturePtr aFeature =
+ std::dynamic_pointer_cast<ModelAPI_Feature>(aFeaturePointAttribute->owner());
+ aTangentFeature->refattr(anAttributeId)->setObject(getFeatureResult(aFeature));
+ }
+#ifdef DEBUG_SPLIT
+ std::cout << " -" << getFeatureInfo(aTangentFeature) << std::endl;
+#endif
+ }
+}
+
+void SketchPlugin_ConstraintSplit::updateRefFeatureConstraints(
+ const ResultPtr& theFeatureBaseResult,
+ const std::list<AttributePtr>& theRefsToFeature)
+{
+ std::list<AttributePtr>::const_iterator anIt = theRefsToFeature.begin(),
+ aLast = theRefsToFeature.end();
+ for (; anIt != aLast; anIt++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
+ if (aRefAttr.get())
+ aRefAttr->setObject(theFeatureBaseResult);
+ }
+}
+
+void SketchPlugin_ConstraintSplit::updateRefAttConstraints(
+ const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
+{
+#ifdef DEBUG_SPLIT
+ std::cout << "SketchPlugin_ConstraintSplit::updateRefAttConstraints" << std::endl;
+#endif
+
+ std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator
+ anIt = theModifiedAttributes.begin(), aLast = theModifiedAttributes.end();
+ for (; anIt != aLast; anIt++) {
+ AttributePtr anAttribute = anIt->first;
+
+ /// not found in references
+ if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end())
+ continue;
+ std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
+ std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
+ aRLast = aRefAttributes.end();
+
+ AttributePtr aNewAttribute = anIt->second;
+ for (; aRefIt != aRLast; aRefIt++) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
+ if (aRefAttr.get()) {
+ aRefAttr->setAttr(aNewAttribute);
+#ifdef DEBUG_SPLIT
+ FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
+ std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
+#endif
+ }
+ }
+ }
+}
+
+void SketchPlugin_ConstraintSplit::splitLine(FeaturePtr& theSplitFeature,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
+{
+ std::set<FeaturePtr> aCreatedFeatures;
+ FeaturePtr aConstraintFeature;
+ theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
+
+ SketchPlugin_Sketch* aSketch = sketch();
+ if (!aSketch)
+ return;
+
+ AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+ data()->attribute(SketchPlugin_Constraint::VALUE()));
+ FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
+ std::string aFeatureKind = aBaseFeature->getKind();
+ if (aFeatureKind != SketchPlugin_Line::ID())
+ return;
+
+ AttributePoint2DPtr aFirstPointAttrOfSplit =
+ getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributePoint2DPtr aSecondPointAttrOfSplit =
+ getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
+
+ getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
+ setError("Error: Feature has no start and end points.");
+ return;
+ }
+
+ arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase,
+ aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+
+#ifdef DEBUG_SPLIT
+ std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
+ std::cout << "Start point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
+ std::cout << "1st point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
+ std::cout << "2nd point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
+ std::cout << "End point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
+#endif
+
+ /// create a split feature
+ theSplitFeature =
+ createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ theCreatedFeatures.insert(theSplitFeature);
+
+ // before split feature
+ if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
+ theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
+ theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
+ }
+ else {
+ theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
+ /// move end arc point to start of split
+ }
+
+ // after split feature
+ if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
+ FeaturePtr aFeature;
+ if (!theBaseFeatureModified.get()) {
+ aFeature = aBaseFeature; ///< use base feature to store all constraints here
+ fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
+ aFeature->execute(); // to update result
+ }
+ else {
+ aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
+ theCreatedFeatures.insert(aFeature);
+ theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
+ aFeature->attribute(SketchPlugin_Line::END_ID())));
+ }
+ aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
+ theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
+ aFeature->attribute(SketchPlugin_Line::START_ID()));
+ theCreatedFeatures.insert(aConstraintFeature);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aFeature->attribute(SketchPlugin_Line::START_ID())));
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aFeature->attribute(SketchPlugin_Line::END_ID())));
+
+ if (!theBaseFeatureModified.get())
+ theBaseFeatureModified = aFeature;
+ else
+ theAfterFeature = aFeature;
+ }
+ else {
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
+ theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
+ theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
+ }
+ // base split, that is defined before split feature should be changed at end
+ // (after the after feature creation). Otherwise modified value will be used in after feature
+ // before split feature
+ if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
+ /// move end arc point to start of split
+ fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
+ aFirstPointAttrOfSplit);
+ theBaseFeatureModified->execute(); // to update result
+ aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
+ theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
+ theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
+ theCreatedFeatures.insert(aConstraintFeature);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
+ }
+ else
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
+
+ // additional constraints between split and base features
+ aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
+ getFeatureResult(aBaseFeature),
+ getFeatureResult(theSplitFeature));
+ theCreatedFeatures.insert(aConstraintFeature);
+ if (theAfterFeature.get()) {
+ aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
+ getFeatureResult(aBaseFeature),
+ getFeatureResult(theAfterFeature));
+ theCreatedFeatures.insert(aConstraintFeature);
+ }
+}