1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: SketchPlugin_ConstraintSplit.cpp
4 // Created: 25 Aug 2016
5 // Author: Natalia ERMOLAEVA
7 #include "SketchPlugin_ConstraintSplit.h"
9 #include <GeomAPI_Pnt2d.h>
10 #include <GeomDataAPI_Point2D.h>
11 #include <ModelAPI_AttributeReference.h>
12 #include <ModelAPI_AttributeString.h>
13 #include <ModelAPI_AttributeRefAttr.h>
14 #include <ModelAPI_Tools.h>
16 #include <ModelAPI_Validator.h>
17 #include <ModelAPI_Session.h>
19 #include <SketchPlugin_Line.h>
20 #include <SketchPlugin_Arc.h>
21 #include <SketchPlugin_Circle.h>
22 #include <SketchPlugin_ConstraintCoincidence.h>
23 #include <SketchPlugin_ConstraintEqual.h>
24 #include <SketchPlugin_ConstraintParallel.h>
25 #include <SketchPlugin_ConstraintTangent.h>
26 #include <SketchPlugin_ConstraintMirror.h>
27 #include <SketchPlugin_MultiRotation.h>
28 #include <SketchPlugin_MultiTranslation.h>
30 #include <ModelAPI_Events.h>
31 #include <SketchPlugin_Line.h>
32 #include <SketchPlugin_Arc.h>
33 #include <SketchPlugin_Circle.h>
35 #include <ModelGeomAlgo_Point2D.h>
36 #include <Events_Loop.h>
43 SketchPlugin_ConstraintSplit::SketchPlugin_ConstraintSplit()
47 void SketchPlugin_ConstraintSplit::initAttributes()
49 data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeReference::typeId());
50 data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
51 data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
54 void SketchPlugin_ConstraintSplit::execute()
56 std::shared_ptr<ModelAPI_Data> aData = data();
58 // Check the base objects are initialized.
59 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
60 aData->attribute(SketchPlugin_Constraint::VALUE()));
61 if(!aBaseObjectAttr->isInitialized()) {
62 setError("Error: Base object is not initialized.");
65 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
66 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
67 if (!aFirstPointAttrOfSplit.get() || !aFirstPointAttrOfSplit->isInitialized() ||
68 !aSecondPointAttrOfSplit.get() || !aSecondPointAttrOfSplit->isInitialized()) {
69 setError("Error: Sub-shape is not initialized.");
73 // Wait all constraints being created, then send update events
74 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
75 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
77 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
80 // Find feature constraints
81 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
82 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
84 std::set<FeaturePtr> aFeaturesToDelete;
85 std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
86 std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
87 //std::map<FeaturePtr, IdToPointPair> aCoincidenceToPoint;
88 getConstraints(aFeaturesToDelete, aTangentFeatures, aCoincidenceToFeature);//, aCoincidenceToPoint);
90 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
91 getRefAttributes(aBaseFeature, aBaseRefAttributes);
93 std::map<AttributePtr, AttributePtr> aBasePointModifiedAttributes;
96 std::cout << std::endl;
97 std::cout << "SketchPlugin_ConstraintSplit::execute()" << std::endl;
98 std::cout << std::endl;
100 SketchPlugin_Sketch* aSketch = sketch();
101 std::cout << "SKETCH FEATURES (before split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
102 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
103 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
106 std::cout << std::endl;
107 std::cout << "IN PARAMETERS" << std::endl;
108 std::cout << "Base feature:" << getFeatureInfo(aBaseFeature) << std::endl;
109 std::cout << std::endl;
111 if (!aCoincidenceToFeature.empty()) {
112 std::cout << "Coincidences to base feature[" << aCoincidenceToFeature.size() << "]: " << std::endl;
113 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToFeature.begin(),
114 aLast = aCoincidenceToFeature.end();
115 for (int i = 1; anIt != aLast; anIt++, i++) {
116 FeaturePtr aFeature = (*anIt).first;
117 std::string anAttributeId = (*anIt).second.first;
118 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
120 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
121 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
122 std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
126 if (!aTangentFeatures.empty()) {
127 std::cout << std::endl;
128 std::cout << "Tangencies to base feature[" << aTangentFeatures.size() << "]: " << std::endl;
129 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aTangentFeatures.begin(),
130 aLast = aTangentFeatures.end();
131 for (int i = 1; anIt != aLast; anIt++, i++) {
132 FeaturePtr aFeature = (*anIt).first;
133 std::string anAttributeId = (*anIt).second.first;
134 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
136 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
137 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
138 std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
142 /*if (!aCoincidenceToPoint.empty()) {
143 std::cout << std::endl;
144 std::cout << "Coincidences to points on base feature[" << aCoincidenceToPoint.size() << "]: " << std::endl;
145 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToPoint.begin(),
146 aLast = aCoincidenceToPoint.end();
147 for (int i = 1; anIt != aLast; anIt++, i++) {
148 FeaturePtr aFeature = (*anIt).first;
149 std::string anAttributeId = (*anIt).second.first;
150 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
152 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
153 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
154 std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
157 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator aRefIt = aBaseRefAttributes.begin(),
158 aRefLast = aBaseRefAttributes.end();
159 std::cout << std::endl << "References to bound point of feature [" << aBaseRefAttributes.size() << "]" << std::endl;
160 for (; aRefIt != aRefLast; aRefIt++) {
161 AttributePtr aBaseAttr = aRefIt->first;
162 std::list<AttributePtr> aRefAttributes = aRefIt->second;
163 std::string aRefsInfo;
164 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
165 aRefAttrLast = aRefAttributes.end();
166 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
167 if (!aRefsInfo.empty())
168 aRefsInfo.append("\n");
169 AttributePtr aRAttr = *aRefAttrIt;
170 aRefsInfo.append(aRAttr->id());
171 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
172 aRefsInfo.append("(" + aRFeature->name() + ") ");
174 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
175 std::cout << " -Point attribute:" << aPointAttr->id().c_str()
176 << "[" << aRefAttributes.size() << "] " <<std::endl << aRefsInfo << std::endl;
179 std::cout << std::endl;
180 std::cout << "---- SPLIT ----" << std::endl;
181 std::cout << std::endl;
184 std::string aFeatureKind = aBaseFeature->getKind();
185 FeaturePtr aSplitFeature, anAfterFeature;
186 std::set<AttributePoint2DPtr> aFurtherCoincidences;
187 std::set<FeaturePtr> aCreatedFeatures;
188 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
189 if (aFeatureKind == SketchPlugin_Line::ID())
190 splitLine(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
191 aModifiedAttributes);
192 else if (aFeatureKind == SketchPlugin_Arc::ID())
193 splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
194 aModifiedAttributes);
195 if (aFeatureKind == SketchPlugin_Circle::ID()) {
196 FeaturePtr aCircleFeature = aBaseFeature;
197 splitCircle(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
198 aModifiedAttributes);
199 aFeaturesToDelete.insert(aCircleFeature);
200 aBaseObjectAttr->setObject(ResultPtr()); // as circle is removed, temporary fill this attribute
204 std::cout << "OUT PARAMETERS" << std::endl;
205 std::cout << "Base modified feature:" << getFeatureInfo(aBaseFeature) << std::endl;
206 std::cout << "Split feature:" << getFeatureInfo(aSplitFeature) << std::endl;
207 std::cout << "After feature:" << getFeatureInfo(anAfterFeature) << std::endl;
208 std::cout << std::endl;
210 std::cout << "Created features by split:[" << aCreatedFeatures.size() << "]" << std::endl;
211 std::set<FeaturePtr>::const_iterator aFIt = aCreatedFeatures.begin(),
212 aFLast = aCreatedFeatures.end();
213 for (; aFIt != aFLast; aFIt++) {
214 std::cout << getFeatureInfo(*aFIt) << std::endl;
216 std::cout << std::endl;
218 std::cout << "Attributes for further Coincidences:" << std::endl;
219 std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
220 aLast = aFurtherCoincidences.end();
221 for (; anIt != aLast; anIt++) {
222 AttributePtr anAttribute = *anIt;
223 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
224 std::cout << ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute)
225 << " [" << getFeatureInfo(aFeature, false) << "]" << std::endl;
228 std::cout << "Modifed attributes (constraints to attributes are moved here):" << std::endl;
229 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator aPIt = aModifiedAttributes.begin(),
230 aPLast = aModifiedAttributes.end();
231 std::string aResInfo;
232 for (; aPIt != aPLast; aPIt++) {
233 if (!aResInfo.empty())
236 std::pair<AttributePtr, AttributePtr> aPair = *aPIt;
238 AttributePtr anAttr = aPair.first;
239 aResInfo.append(anAttr->id());
240 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->owner());
241 aResInfo.append("(" + aFeature->name() + ") ");
243 aResInfo.append(" - is modified to - ");
245 anAttr = aPair.second;
246 aResInfo.append(anAttr->id());
247 aFeature = ModelAPI_Feature::feature(anAttr->owner());
248 aResInfo.append("(" + aFeature->name() + ") ");
250 std::cout << aResInfo << std::endl;
253 std::set<ResultPtr> aFeatureResults;
254 aFeatureResults.insert(getFeatureResult(aBaseFeature));
255 if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
256 aFeatureResults.insert(getFeatureResult(anAfterFeature));
258 // coincidence to feature
259 updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
261 // coincidence to points
262 //updateCoincidenceConstraintsToFeature(aCoincidenceToPoint, aFurtherCoincidences,
263 // std::set<ResultPtr>());
265 updateTangentConstraintsToFeature(aTangentFeatures, aFurtherCoincidences);
267 updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
269 // delete constraints
271 std::cout << "remove features and references:" << std::endl;
272 std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
273 aDLast = aFeaturesToDelete.end();
274 for (; aDIt != aDLast; aDIt++) {
275 std::cout << getFeatureInfo(*aDIt, false) << std::endl;
276 std::cout << std::endl;
279 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
281 // Send events to update the sub-features by the solver.
282 if(isUpdateFlushed) {
283 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
287 std::cout << "SKETCH FEATURES (after split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
288 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
289 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
294 bool SketchPlugin_ConstraintSplit::isMacro() const
299 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_ConstraintSplit::getPointOfRefAttr(
300 const AttributePtr& theAttribute)
302 AttributePoint2DPtr aPointAttribute;
304 if (theAttribute->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
305 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
306 if (aRefAttr.get() && aRefAttr->isInitialized()) {
307 AttributePtr anAttribute = aRefAttr->attr();
308 if (anAttribute.get() && anAttribute->attributeType() == GeomDataAPI_Point2D::typeId())
309 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
312 return aPointAttribute;
315 void SketchPlugin_ConstraintSplit::getFeaturePoints(AttributePoint2DPtr& theStartPointAttr,
316 AttributePoint2DPtr& theEndPointAttr)
318 AttributePoint2DPtr aPointAttribute;
320 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
321 data()->attribute(SketchPlugin_Constraint::VALUE()));
322 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
324 std::string aFeatureKind = aBaseFeature->getKind();
325 std::string aStartAttributeName, anEndAttributeName;
326 if (aFeatureKind == SketchPlugin_Line::ID()) {
327 aStartAttributeName = SketchPlugin_Line::START_ID();
328 anEndAttributeName = SketchPlugin_Line::END_ID();
330 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
331 aStartAttributeName = SketchPlugin_Arc::START_ID();
332 anEndAttributeName = SketchPlugin_Arc::END_ID();
334 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
335 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
336 aBaseFeature->attribute(aStartAttributeName));
337 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
338 aBaseFeature->attribute(anEndAttributeName));
342 void SketchPlugin_ConstraintSplit::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
343 std::map<FeaturePtr, IdToPointPair>& theTangentFeatures,
344 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature/*,
345 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToPoint*/)
347 std::shared_ptr<ModelAPI_Data> aData = data();
349 // Check the base objects are initialized.
350 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
351 aData->attribute(SketchPlugin_Constraint::VALUE()));
352 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
353 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
355 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
356 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
357 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
359 std::set<AttributePtr>::const_iterator aIt;
360 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
361 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
362 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
363 std::string aRefFeatureKind = aRefFeature->getKind();
364 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
365 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
366 aRefFeatureKind == SketchPlugin_MultiTranslation::ID())
367 theFeaturesToDelete.insert(aRefFeature);
368 else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) {
369 if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) /// TEMPORARY limitaion
370 theFeaturesToDelete.insert(aRefFeature); /// until tangency between arc and line is implemented
372 std::string anAttributeToBeModified;
373 AttributePoint2DPtr aTangentPoint;
374 ObjectPtr aResult1 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->object();
375 ObjectPtr aResult2 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B())->object();
376 if (aResult1.get() && aResult2.get()) {
377 FeaturePtr aCoincidenceFeature = SketchPlugin_ConstraintCoincidence::findCoincidenceFeature
378 (ModelAPI_Feature::feature(aResult1),
379 ModelAPI_Feature::feature(aResult2));
380 aTangentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aCoincidenceFeature);
382 if (aTangentPoint.get()) {
383 FeaturePtr aFeature1 = ModelAPI_Feature::feature(aResult1);
384 std::string anAttributeToBeModified = aFeature1 == aBaseFeature
385 ? SketchPlugin_Constraint::ENTITY_A() : SketchPlugin_Constraint::ENTITY_B();
386 theTangentFeatures[aRefFeature] = std::make_pair(anAttributeToBeModified, aTangentPoint);
389 theFeaturesToDelete.insert(aRefFeature); /// there is not coincident point between tangent constraint
392 else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) {
393 std::string anAttributeToBeModified;
394 AttributePoint2DPtr aCoincidentPoint;
395 AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
396 AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
397 bool isToFeature = false;
398 if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature
399 FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
401 isToFeature = aFeature.get() && aFeature == aBaseFeature;
402 anAttributeToBeModified = anAttrA->id();
404 aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object())
406 isToFeature = aFeature.get() && aFeature == aBaseFeature;
407 anAttributeToBeModified = anAttrB->id();
410 aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
412 if (!isToFeature) { /// coincidence to point on base feature
413 AttributePtr anAttribute;
415 if (!anAttrA->isObject()) {
416 AttributePtr aCurAttribute = anAttrA->attr();
417 if (aCurAttribute.get()) {
418 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
419 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
420 anAttribute = anAttrB->attr();
421 anAttributeToBeModified = anAttrA->id();
425 if (!anAttribute.get() && !anAttrB->isObject()) {
426 AttributePtr aCurAttribute = anAttrB->attr();
427 if (aCurAttribute.get()) {
428 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
429 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
430 anAttribute = anAttrA->attr();
431 anAttributeToBeModified = anAttrB->id();
435 if (anAttribute.get())
436 aCoincidentPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
438 if (aCoincidentPoint.get()) {
440 theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified,
443 //theCoincidenceToPoint[aRefFeature] = std::make_pair(anAttributeToBeModified,
444 // aCoincidentPoint);
447 theFeaturesToDelete.insert(aRefFeature); /// this case should not happen
452 void SketchPlugin_ConstraintSplit::getRefAttributes(const FeaturePtr& theFeature,
453 std::map<AttributePtr, std::list<AttributePtr> >& theRefs)
457 std::list<AttributePtr> aPointAttributes = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
458 std::set<AttributePtr> aPointAttributesSet;
460 std::list<AttributePtr>::const_iterator aPIt = aPointAttributes.begin(), aPLast = aPointAttributes.end();
461 for (; aPIt != aPLast; aPIt++)
462 aPointAttributesSet.insert(*aPIt);
464 const std::set<AttributePtr>& aRefsAttributes = theFeature->data()->refsToMe();
465 std::set<AttributePtr>::const_iterator aIt;
466 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
467 AttributePtr anAttr = (*aIt);
468 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
469 if (anAttrFeature.get() != this &&
470 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
471 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
472 if (!aRefAttr->isObject()) {
473 AttributePtr anAttrInRef = aRefAttr->attr();
474 if (anAttrInRef.get() && aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
475 if (theRefs.find(anAttrInRef) != theRefs.end())
476 theRefs[anAttrInRef].push_back(aRefAttr);
478 std::list<AttributePtr> anAttrList;
479 anAttrList.push_back(aRefAttr);
480 theRefs[anAttrInRef] = anAttrList;
488 void SketchPlugin_ConstraintSplit::updateCoincidenceConstraintsToFeature(
489 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
490 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
491 const std::set<ResultPtr>& theFeatureResults)
493 if (theCoincidenceToFeature.empty())
496 std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
497 aCLast = theCoincidenceToFeature.end();
499 std::cout << std::endl;
500 std::cout << "Coincidences to feature(modified):"<< std::endl;
502 for (; aCIt != aCLast; aCIt++) {
503 FeaturePtr aCoincFeature = aCIt->first;
504 std::string anAttributeId = aCIt->second.first;
505 AttributePoint2DPtr aCoincPoint = aCIt->second.second;
506 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
507 aFCLast = theFurtherCoincidences.end();
508 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aCoincPoint->pnt();
509 AttributePoint2DPtr aFeaturePointAttribute;
510 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
511 AttributePoint2DPtr aFCAttribute = *aFCIt;
512 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
513 aFeaturePointAttribute = aFCAttribute;
515 if (aFeaturePointAttribute.get()) {
516 aCoincFeature->refattr(anAttributeId)->setAttr(aFeaturePointAttribute);
519 /// find feature by shape intersected the point
520 ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
522 if (theFeatureResults.size() > 1) { // try to find point on additional feature
523 ResultPtr anAddtionalResult = *(theFeatureResults.begin()++);
524 GeomShapePtr aShape = anAddtionalResult->shape();
526 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aCoincPoint->pnt();
527 std::shared_ptr<GeomAPI_Pnt> aPoint = sketch()->to3D(aPnt2d->x(), aPnt2d->y());
529 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
530 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPoint, aProjectedPoint))
531 aResultForCoincidence = anAddtionalResult;
533 aCoincFeature->refattr(anAttributeId)->setObject(aResultForCoincidence);
536 std::cout << " -" << getFeatureInfo(aCoincFeature) << std::endl;
541 void SketchPlugin_ConstraintSplit::updateTangentConstraintsToFeature(
542 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theTangentFeatures,
543 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences)
545 if (theTangentFeatures.empty())
548 std::map<FeaturePtr, IdToPointPair>::const_iterator aTIt = theTangentFeatures.begin(),
549 aTLast = theTangentFeatures.end();
551 std::cout << std::endl;
552 std::cout << "Tangencies to feature(modified):"<< std::endl;
554 for (; aTIt != aTLast; aTIt++) {
555 FeaturePtr aTangentFeature = aTIt->first;
556 std::string anAttributeId = aTIt->second.first;
557 AttributePoint2DPtr aTangentPoint = aTIt->second.second;
558 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
559 aFCLast = theFurtherCoincidences.end();
560 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aTangentPoint->pnt();
561 AttributePoint2DPtr aFeaturePointAttribute;
562 /// here we rely on created coincidence between further coincidence point and tangent result
563 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
564 AttributePoint2DPtr aFCAttribute = *aFCIt;
565 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
566 aFeaturePointAttribute = aFCAttribute;
568 if (aFeaturePointAttribute.get()) {
569 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aFeaturePointAttribute->owner());
570 aTangentFeature->refattr(anAttributeId)->setObject(getFeatureResult(aFeature));
573 std::cout << " -" << getFeatureInfo(aTangentFeature) << std::endl;
578 void SketchPlugin_ConstraintSplit::updateRefAttConstraints(
579 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
580 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
583 std::cout << "SketchPlugin_ConstraintSplit::updateRefAttConstraints" << std::endl;
586 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator anIt = theModifiedAttributes.begin(),
587 aLast = theModifiedAttributes.end();
588 for (; anIt != aLast; anIt++) {
589 AttributePtr anAttribute = anIt->first;
591 if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) /// not found in references
593 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
594 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
595 aRLast = aRefAttributes.end();
597 AttributePtr aNewAttribute = anIt->second;
598 for (; aRefIt != aRLast; aRefIt++) {
599 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
600 if (aRefAttr.get()) {
601 aRefAttr->setAttr(aNewAttribute);
603 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
604 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
611 void SketchPlugin_ConstraintSplit::splitLine(FeaturePtr& theSplitFeature,
612 FeaturePtr& theBaseFeatureModified,
613 FeaturePtr& theAfterFeature,
614 std::set<AttributePoint2DPtr>& thePoints,
615 std::set<FeaturePtr>& theCreatedFeatures,
616 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
618 std::set<FeaturePtr> aCreatedFeatures;
619 FeaturePtr aConstraintFeature;
620 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
622 SketchPlugin_Sketch* aSketch = sketch();
626 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
627 data()->attribute(SketchPlugin_Constraint::VALUE()));
628 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
629 std::string aFeatureKind = aBaseFeature->getKind();
630 if (aFeatureKind != SketchPlugin_Line::ID())
633 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
634 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
635 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
636 getFeaturePoints(aStartPointAttrOfBase, anEndPointAttrOfBase);
637 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
638 setError("Error: Feature has no start and end points.");
642 arrangePoints(aStartPointAttrOfBase, anEndPointAttrOfBase, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
644 /// create a split feature
645 theSplitFeature = createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
646 theCreatedFeatures.insert(theSplitFeature);
648 // before split feature
649 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
650 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
651 theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
654 theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
655 /// move end arc point to start of split
658 // after split feature
659 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
661 if (!theBaseFeatureModified.get()) {
662 aFeature = aBaseFeature; ///< use base feature to store all constraints here
663 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
664 aFeature->execute(); // to update result
667 aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
668 theCreatedFeatures.insert(aFeature);
669 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
670 aFeature->attribute(SketchPlugin_Line::END_ID())));
672 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
673 theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
674 aFeature->attribute(SketchPlugin_Line::START_ID()));
675 theCreatedFeatures.insert(aConstraintFeature);
677 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
678 (aFeature->attribute(SketchPlugin_Line::START_ID())));
679 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
680 (aFeature->attribute(SketchPlugin_Line::END_ID())));
682 if (!theBaseFeatureModified.get())
683 theBaseFeatureModified = aFeature;
685 theAfterFeature = aFeature;
688 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
689 (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
690 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
691 theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
693 // base split, that is defined before split feature should be changed at end
694 // (after the after feature creation). Otherwise modified value will be used in after feature
695 // before split feature
696 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
697 /// move end arc point to start of split
698 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()), aFirstPointAttrOfSplit);
699 theBaseFeatureModified->execute(); // to update result
700 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
701 theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
702 theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
703 theCreatedFeatures.insert(aConstraintFeature);
705 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
706 (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
707 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
708 (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
711 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
712 (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
714 // additional constraints between split and base features
715 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
716 getFeatureResult(aBaseFeature),
717 getFeatureResult(theSplitFeature));
718 theCreatedFeatures.insert(aConstraintFeature);
719 if (theAfterFeature.get()) {
720 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
721 getFeatureResult(aBaseFeature),
722 getFeatureResult(theAfterFeature));
723 theCreatedFeatures.insert(aConstraintFeature);
727 void SketchPlugin_ConstraintSplit::splitArc(FeaturePtr& theSplitFeature,
728 FeaturePtr& theBaseFeatureModified,
729 FeaturePtr& theAfterFeature,
730 std::set<AttributePoint2DPtr>& thePoints,
731 std::set<FeaturePtr>& theCreatedFeatures,
732 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
734 std::set<FeaturePtr> aCreatedFeatures;
735 FeaturePtr aConstraintFeature;
736 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
738 SketchPlugin_Sketch* aSketch = sketch();
742 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
743 data()->attribute(SketchPlugin_Constraint::VALUE()));
744 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
745 std::string aFeatureKind = aBaseFeature->getKind();
746 if (aFeatureKind != SketchPlugin_Arc::ID())
749 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
750 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
751 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
752 getFeaturePoints(aStartPointAttrOfBase, anEndPointAttrOfBase);
753 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
754 setError("Error: Feature has no start and end points.");
758 arrangePoints(aStartPointAttrOfBase, anEndPointAttrOfBase, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
761 theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
762 theCreatedFeatures.insert(theSplitFeature);
764 // before split feature
765 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
766 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
767 theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
770 theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
771 /// move end arc point to start of split
774 // after split feature
775 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
777 if (!theBaseFeatureModified.get()) {
778 aFeature = aBaseFeature; ///< use base feature to store all constraints here
779 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
780 aFeature->execute(); // to update result
783 aFeature = createArcFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
784 theCreatedFeatures.insert(aFeature);
785 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
786 aFeature->attribute(SketchPlugin_Arc::END_ID())));
788 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
789 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
790 aFeature->attribute(SketchPlugin_Arc::START_ID()));
791 theCreatedFeatures.insert(aConstraintFeature);
793 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
794 (aFeature->attribute(SketchPlugin_Arc::START_ID())));
795 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
796 (aFeature->attribute(SketchPlugin_Arc::END_ID())));
798 if (!theBaseFeatureModified.get())
799 theBaseFeatureModified = aFeature;
801 theAfterFeature = aFeature;
804 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
805 (theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
806 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
807 theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
809 // base split, that is defined before split feature should be changed at end
810 // (after the after feature creation). Otherwise modified value will be used in after feature
811 // before split feature
812 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
813 /// move end arc point to start of split
814 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()), aFirstPointAttrOfSplit);
815 theBaseFeatureModified->execute(); // to update result
816 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
817 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
818 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
819 theCreatedFeatures.insert(aConstraintFeature);
821 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
822 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
823 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
824 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
827 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
828 (theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
830 // additional constraints between split and base features
831 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
832 getFeatureResult(aBaseFeature),
833 getFeatureResult(theSplitFeature));
834 theCreatedFeatures.insert(aConstraintFeature);
835 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
836 getFeatureResult(theSplitFeature),
837 getFeatureResult(aBaseFeature));
838 theCreatedFeatures.insert(aConstraintFeature);
839 if (theAfterFeature.get()) {
840 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
841 getFeatureResult(aBaseFeature),
842 getFeatureResult(theAfterFeature));
843 theCreatedFeatures.insert(aConstraintFeature);
844 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
845 getFeatureResult(theSplitFeature),
846 getFeatureResult(theAfterFeature));
847 theCreatedFeatures.insert(aConstraintFeature);
851 void SketchPlugin_ConstraintSplit::splitCircle(FeaturePtr& theSplitFeature,
852 FeaturePtr& theBaseFeatureModified,
853 FeaturePtr& theAfterFeature,
854 std::set<AttributePoint2DPtr>& thePoints,
855 std::set<FeaturePtr>& theCreatedFeatures,
856 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
858 std::set<FeaturePtr> aCreatedFeatures;
859 FeaturePtr aConstraintFeature;
860 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
862 SketchPlugin_Sketch* aSketch = sketch();
866 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
867 data()->attribute(SketchPlugin_Constraint::VALUE()));
868 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
869 std::string aFeatureKind = aBaseFeature->getKind();
870 if (aFeatureKind != SketchPlugin_Circle::ID())
873 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
874 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
877 theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
878 bool aSplitReversed = std::dynamic_pointer_cast<SketchPlugin_Arc>(theSplitFeature)->isReversed();
879 theCreatedFeatures.insert(theSplitFeature);
881 /// base feature is a left part of the circle
882 theBaseFeatureModified = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
883 std::dynamic_pointer_cast<SketchPlugin_Arc>(theBaseFeatureModified)->setReversed(!aSplitReversed);
884 theBaseFeatureModified->execute();
886 theModifiedAttributes.insert(std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
887 theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
889 theCreatedFeatures.insert(theBaseFeatureModified);
891 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
892 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
893 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
894 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
896 // additional constraints between split and base features
897 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
898 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
899 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()));
900 theCreatedFeatures.insert(aConstraintFeature);
901 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
902 theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()),
903 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
904 theCreatedFeatures.insert(aConstraintFeature);
906 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
907 getFeatureResult(theSplitFeature),
908 getFeatureResult(theBaseFeatureModified));
909 theCreatedFeatures.insert(aConstraintFeature);
912 void SketchPlugin_ConstraintSplit::arrangePoints(const AttributePoint2DPtr& theStartPointAttr,
913 const AttributePoint2DPtr& theEndPointAttr,
914 AttributePoint2DPtr& theFirstPointAttr,
915 AttributePoint2DPtr& theLastPointAttr)
917 /// if first point is closer to last point, wrap first and last values
918 if (theStartPointAttr->pnt()->distance(theFirstPointAttr->pnt()) >
919 theStartPointAttr->pnt()->distance(theLastPointAttr->pnt())) {
920 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
921 theFirstPointAttr = theLastPointAttr;
922 theLastPointAttr = aTmpPoint;
926 void SketchPlugin_ConstraintSplit::fillAttribute(const AttributePtr& theModifiedAttribute,
927 const AttributePtr& theSourceAttribute)
929 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
930 theModifiedAttribute);
931 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
934 if (aModifiedAttribute.get() && aSourceAttribute.get())
935 aModifiedAttribute->setValue(aSourceAttribute->pnt());
938 FeaturePtr SketchPlugin_ConstraintSplit::createLineFeature(const FeaturePtr& theBaseFeature,
939 const AttributePtr& theFirstPointAttr,
940 const AttributePtr& theSecondPointAttr)
943 SketchPlugin_Sketch* aSketch = sketch();
944 if (!aSketch || !theBaseFeature.get())
947 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
949 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPointAttr);
950 fillAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPointAttr);
951 aFeature->execute(); // to obtain result
956 FeaturePtr SketchPlugin_ConstraintSplit::createArcFeature(const FeaturePtr& theBaseFeature,
957 const AttributePtr& theFirstPointAttr,
958 const AttributePtr& theSecondPointAttr)
961 SketchPlugin_Sketch* aSketch = sketch();
962 if (!aSketch || !theBaseFeature.get())
965 std::string aCenterAttributeId;
966 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
967 aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
968 else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
969 aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
971 if (aCenterAttributeId.empty())
974 aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
975 // update fillet arc: make the arc correct for sure, so, it is not needed to process the "attribute updated"
976 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
977 aFeature->data()->blockSendAttributeUpdated(true);
979 aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
980 SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
982 fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
983 theBaseFeature->attribute(aCenterAttributeId));
984 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
985 fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
986 aFeature->data()->blockSendAttributeUpdated(false);
987 aFeature->execute(); // to obtain result
992 FeaturePtr SketchPlugin_ConstraintSplit::createConstraint(const std::string& theConstraintId,
993 const AttributePtr& theFirstAttribute,
994 const AttributePtr& theSecondAttribute)
996 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
997 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
998 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
999 aRefAttr->setAttr(theFirstAttribute);
1001 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1002 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1003 aRefAttr->setAttr(theSecondAttribute);
1008 FeaturePtr SketchPlugin_ConstraintSplit::createConstraintForObjects(const std::string& theConstraintId,
1009 const ObjectPtr& theFirstObject,
1010 const ObjectPtr& theSecondObject)
1012 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1013 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1014 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1015 aRefAttr->setObject(theFirstObject);
1017 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1018 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1019 aRefAttr->setObject(theSecondObject);
1024 std::shared_ptr<ModelAPI_Result> SketchPlugin_ConstraintSplit::getFeatureResult(
1025 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1027 std::shared_ptr<ModelAPI_Result> aResult;
1029 std::string aFeatureKind = theFeature->getKind();
1030 if (aFeatureKind == SketchPlugin_Line::ID())
1031 aResult = theFeature->firstResult();
1032 else if (aFeatureKind == SketchPlugin_Arc::ID())
1033 aResult = theFeature->lastResult();
1034 else if (aFeatureKind == SketchPlugin_Circle::ID())
1035 aResult = theFeature->lastResult();
1040 std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_ConstraintSplit::getEdgeAttributes(
1041 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1043 std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
1045 std::string aFeatureKind = theFeature->getKind();
1046 if (aFeatureKind == SketchPlugin_Line::ID()) {
1047 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::START_ID()));
1048 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::END_ID()));
1050 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
1051 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
1052 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
1054 else if (aFeatureKind == SketchPlugin_Circle::ID()) {
1057 return anAttributes;
1061 std::string SketchPlugin_ConstraintSplit::getFeatureInfo(
1062 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1063 const bool isUseAttributesInfo)
1066 if (!theFeature.get()) {
1070 if (theFeature->data()->isValid())
1071 anInfo.append(theFeature->data()->name().c_str());
1073 if (isUseAttributesInfo) {
1074 std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
1075 getEdgeAttributes(theFeature));
1076 if (!aPointsInfo.empty()) { /// processing of feature with point 2d attributes, like line, arc, circle
1079 anInfo += aPointsInfo;
1081 else { /// process constraint coincidence, find points in ref attr attributes
1082 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
1083 ModelAPI_AttributeRefAttr::typeId());
1084 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
1085 std::string anAttributesInfo;
1086 for(; anIt != aLast; anIt++) {
1087 if (!anAttributesInfo.empty()) {
1088 anAttributesInfo.append(", ");
1089 anAttributesInfo += "\n";
1091 AttributePtr anAttr = *anIt;
1092 std::string aValue = "not defined";
1093 std::string aType = anAttr->attributeType();
1094 if (aType == ModelAPI_AttributeRefAttr::typeId()) {
1095 std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
1096 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
1097 if (aRefAttr.get()) {
1098 if (aRefAttr->isObject()) {
1099 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1100 aValue = "<object:>" + getFeatureInfo(aFeature, false);
1103 AttributePtr anAttribute = aRefAttr->attr();
1104 if (anAttribute.get()) {
1105 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
1106 aValue = "<attr:>" + ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute) +
1107 " [" + getFeatureInfo(aFeature, false) + "]";
1112 anAttributesInfo.append(" " + anAttr->id() + ": " + aValue);
1114 if (!anAttributesInfo.empty())
1115 anInfo = anInfo + "\n" + anAttributesInfo;