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_Dir2d.h>
10 #include <GeomAPI_Pnt2d.h>
11 #include <GeomAPI_XY.h>
12 #include <GeomDataAPI_Point2D.h>
13 #include <ModelAPI_AttributeReference.h>
14 #include <ModelAPI_AttributeString.h>
15 #include <ModelAPI_AttributeRefAttr.h>
16 #include <ModelAPI_Tools.h>
18 #include <ModelAPI_Validator.h>
19 #include <ModelAPI_Session.h>
21 #include <SketchPlugin_Line.h>
22 #include <SketchPlugin_Arc.h>
23 #include <SketchPlugin_Circle.h>
24 #include <SketchPlugin_ConstraintCoincidence.h>
25 #include <SketchPlugin_ConstraintEqual.h>
26 #include <SketchPlugin_ConstraintParallel.h>
27 #include <SketchPlugin_ConstraintTangent.h>
28 #include <SketchPlugin_ConstraintMirror.h>
29 #include <SketchPlugin_MultiRotation.h>
30 #include <SketchPlugin_MultiTranslation.h>
32 #include <ModelAPI_Events.h>
33 #include <SketchPlugin_Line.h>
34 #include <SketchPlugin_Arc.h>
35 #include <SketchPlugin_Circle.h>
37 #include <ModelGeomAlgo_Point2D.h>
38 #include <Events_Loop.h>
47 static const double PI = 3.141592653589793238463;
49 SketchPlugin_ConstraintSplit::SketchPlugin_ConstraintSplit()
53 void SketchPlugin_ConstraintSplit::initAttributes()
55 data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeReference::typeId());
56 data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
57 data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
60 void SketchPlugin_ConstraintSplit::execute()
62 std::shared_ptr<ModelAPI_Data> aData = data();
64 // Check the base objects are initialized.
65 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
66 aData->attribute(SketchPlugin_Constraint::VALUE()));
67 if(!aBaseObjectAttr->isInitialized()) {
68 setError("Error: Base object is not initialized.");
71 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
72 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
73 if (!aFirstPointAttrOfSplit.get() || !aFirstPointAttrOfSplit->isInitialized() ||
74 !aSecondPointAttrOfSplit.get() || !aSecondPointAttrOfSplit->isInitialized()) {
75 setError("Error: Sub-shape is not initialized.");
79 // Wait all constraints being created, then send update events
80 static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
81 bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
83 Events_Loop::loop()->setFlushed(anUpdateEvent, false);
86 // Find feature constraints
87 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
88 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
90 std::set<FeaturePtr> aFeaturesToDelete;
91 std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
92 std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
93 //std::map<FeaturePtr, IdToPointPair> aCoincidenceToPoint;
94 getConstraints(aFeaturesToDelete, aTangentFeatures, aCoincidenceToFeature);//, aCoincidenceToPoint);
96 std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
97 getRefAttributes(aBaseFeature, aBaseRefAttributes);
99 std::map<AttributePtr, AttributePtr> aBasePointModifiedAttributes;
102 std::cout << std::endl;
103 std::cout << "SketchPlugin_ConstraintSplit::execute()" << std::endl;
104 std::cout << std::endl;
106 SketchPlugin_Sketch* aSketch = sketch();
107 std::cout << "SKETCH FEATURES (before split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
108 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
109 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
112 std::cout << std::endl;
113 std::cout << "IN PARAMETERS" << std::endl;
114 std::cout << "Base feature:" << getFeatureInfo(aBaseFeature) << std::endl;
115 std::cout << std::endl;
117 if (!aCoincidenceToFeature.empty()) {
118 std::cout << "Coincidences to base feature[" << aCoincidenceToFeature.size() << "]: " << std::endl;
119 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToFeature.begin(),
120 aLast = aCoincidenceToFeature.end();
121 for (int i = 1; anIt != aLast; anIt++, i++) {
122 FeaturePtr aFeature = (*anIt).first;
123 std::string anAttributeId = (*anIt).second.first;
124 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
126 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
127 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
128 std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
132 if (!aTangentFeatures.empty()) {
133 std::cout << std::endl;
134 std::cout << "Tangencies to base feature[" << aTangentFeatures.size() << "]: " << std::endl;
135 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aTangentFeatures.begin(),
136 aLast = aTangentFeatures.end();
137 for (int i = 1; anIt != aLast; anIt++, i++) {
138 FeaturePtr aFeature = (*anIt).first;
139 std::string anAttributeId = (*anIt).second.first;
140 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
142 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
143 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
144 std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
148 /*if (!aCoincidenceToPoint.empty()) {
149 std::cout << std::endl;
150 std::cout << "Coincidences to points on base feature[" << aCoincidenceToPoint.size() << "]: " << std::endl;
151 std::map<FeaturePtr, IdToPointPair>::const_iterator anIt = aCoincidenceToPoint.begin(),
152 aLast = aCoincidenceToPoint.end();
153 for (int i = 1; anIt != aLast; anIt++, i++) {
154 FeaturePtr aFeature = (*anIt).first;
155 std::string anAttributeId = (*anIt).second.first;
156 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = (*anIt).second.second;
158 std::cout << i << "-" << getFeatureInfo(aFeature) << std::endl;
159 std::cout << " -Attribute to correct:" << anAttributeId << std::endl;
160 std::cout << " -Point attribute:" << ModelGeomAlgo_Point2D::getPointAttributeInfo(aPointAttr) << std::endl;
163 std::map<AttributePtr, std::list<AttributePtr> >::const_iterator aRefIt = aBaseRefAttributes.begin(),
164 aRefLast = aBaseRefAttributes.end();
165 std::cout << std::endl << "References to bound point of feature [" << aBaseRefAttributes.size() << "]" << std::endl;
166 for (; aRefIt != aRefLast; aRefIt++) {
167 AttributePtr aBaseAttr = aRefIt->first;
168 std::list<AttributePtr> aRefAttributes = aRefIt->second;
169 std::string aRefsInfo;
170 std::list<AttributePtr>::const_iterator aRefAttrIt = aRefAttributes.begin(),
171 aRefAttrLast = aRefAttributes.end();
172 for (; aRefAttrIt != aRefAttrLast; aRefAttrIt++) {
173 if (!aRefsInfo.empty())
174 aRefsInfo.append("\n");
175 AttributePtr aRAttr = *aRefAttrIt;
176 aRefsInfo.append(aRAttr->id());
177 FeaturePtr aRFeature = ModelAPI_Feature::feature(aRAttr->owner());
178 aRefsInfo.append("(" + aRFeature->name() + ") ");
180 std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aBaseAttr);
181 std::cout << " -Point attribute:" << aPointAttr->id().c_str()
182 << "[" << aRefAttributes.size() << "] " <<std::endl << aRefsInfo << std::endl;
185 std::cout << std::endl;
186 std::cout << "---- SPLIT ----" << std::endl;
187 std::cout << std::endl;
190 std::string aFeatureKind = aBaseFeature->getKind();
191 FeaturePtr aSplitFeature, anAfterFeature;
192 std::set<AttributePoint2DPtr> aFurtherCoincidences;
193 std::set<FeaturePtr> aCreatedFeatures;
194 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
195 if (aFeatureKind == SketchPlugin_Line::ID())
196 splitLine(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
197 aModifiedAttributes);
198 else if (aFeatureKind == SketchPlugin_Arc::ID())
199 splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
200 aModifiedAttributes);
201 if (aFeatureKind == SketchPlugin_Circle::ID()) {
202 FeaturePtr aCircleFeature = aBaseFeature;
203 splitCircle(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
204 aModifiedAttributes);
205 aFeaturesToDelete.insert(aCircleFeature);
206 aBaseObjectAttr->setObject(ResultPtr()); // as circle is removed, temporary fill this attribute
210 std::cout << "OUT PARAMETERS" << std::endl;
211 std::cout << "Base modified feature:" << getFeatureInfo(aBaseFeature) << std::endl;
212 std::cout << "Split feature:" << getFeatureInfo(aSplitFeature) << std::endl;
213 std::cout << "After feature:" << getFeatureInfo(anAfterFeature) << std::endl;
214 std::cout << std::endl;
216 std::cout << "Created features by split:[" << aCreatedFeatures.size() << "]" << std::endl;
217 std::set<FeaturePtr>::const_iterator aFIt = aCreatedFeatures.begin(),
218 aFLast = aCreatedFeatures.end();
219 for (; aFIt != aFLast; aFIt++) {
220 std::cout << getFeatureInfo(*aFIt) << std::endl;
222 std::cout << std::endl;
224 std::cout << "Attributes for further Coincidences:" << std::endl;
225 std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
226 aLast = aFurtherCoincidences.end();
227 for (; anIt != aLast; anIt++) {
228 AttributePtr anAttribute = *anIt;
229 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
230 std::cout << ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute)
231 << " [" << getFeatureInfo(aFeature, false) << "]" << std::endl;
234 std::cout << "Modifed attributes (constraints to attributes are moved here):" << std::endl;
235 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator aPIt = aModifiedAttributes.begin(),
236 aPLast = aModifiedAttributes.end();
237 std::string aResInfo;
238 for (; aPIt != aPLast; aPIt++) {
239 if (!aResInfo.empty())
242 std::pair<AttributePtr, AttributePtr> aPair = *aPIt;
244 AttributePtr anAttr = aPair.first;
245 aResInfo.append(anAttr->id());
246 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->owner());
247 aResInfo.append("(" + aFeature->name() + ") ");
249 aResInfo.append(" - is modified to - ");
251 anAttr = aPair.second;
252 aResInfo.append(anAttr->id());
253 aFeature = ModelAPI_Feature::feature(anAttr->owner());
254 aResInfo.append("(" + aFeature->name() + ") ");
256 std::cout << aResInfo << std::endl;
259 std::set<ResultPtr> aFeatureResults;
260 aFeatureResults.insert(getFeatureResult(aBaseFeature));
261 if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
262 aFeatureResults.insert(getFeatureResult(anAfterFeature));
264 // coincidence to feature
265 updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
267 // coincidence to points
268 //updateCoincidenceConstraintsToFeature(aCoincidenceToPoint, aFurtherCoincidences,
269 // std::set<ResultPtr>());
271 updateTangentConstraintsToFeature(aTangentFeatures, aFurtherCoincidences);
273 updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
275 // delete constraints
277 std::cout << "remove features and references:" << std::endl;
278 std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
279 aDLast = aFeaturesToDelete.end();
280 for (; aDIt != aDLast; aDIt++) {
281 std::cout << getFeatureInfo(*aDIt, false) << std::endl;
282 std::cout << std::endl;
285 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
287 // Send events to update the sub-features by the solver.
288 if(isUpdateFlushed) {
289 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
293 std::cout << "SKETCH FEATURES (after split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
294 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
295 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
300 bool SketchPlugin_ConstraintSplit::isMacro() const
305 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_ConstraintSplit::getPointOfRefAttr(
306 const AttributePtr& theAttribute)
308 AttributePoint2DPtr aPointAttribute;
310 if (theAttribute->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
311 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
312 if (aRefAttr.get() && aRefAttr->isInitialized()) {
313 AttributePtr anAttribute = aRefAttr->attr();
314 if (anAttribute.get() && anAttribute->attributeType() == GeomDataAPI_Point2D::typeId())
315 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
318 return aPointAttribute;
321 void SketchPlugin_ConstraintSplit::getFeaturePoints(AttributePoint2DPtr& theStartPointAttr,
322 AttributePoint2DPtr& theEndPointAttr)
324 AttributePoint2DPtr aPointAttribute;
326 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
327 data()->attribute(SketchPlugin_Constraint::VALUE()));
328 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
330 std::string aFeatureKind = aBaseFeature->getKind();
331 std::string aStartAttributeName, anEndAttributeName;
332 if (aFeatureKind == SketchPlugin_Line::ID()) {
333 aStartAttributeName = SketchPlugin_Line::START_ID();
334 anEndAttributeName = SketchPlugin_Line::END_ID();
336 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
337 aStartAttributeName = SketchPlugin_Arc::START_ID();
338 anEndAttributeName = SketchPlugin_Arc::END_ID();
340 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
341 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
342 aBaseFeature->attribute(aStartAttributeName));
343 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
344 aBaseFeature->attribute(anEndAttributeName));
348 void SketchPlugin_ConstraintSplit::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
349 std::map<FeaturePtr, IdToPointPair>& theTangentFeatures,
350 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature/*,
351 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToPoint*/)
353 std::shared_ptr<ModelAPI_Data> aData = data();
355 // Check the base objects are initialized.
356 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
357 aData->attribute(SketchPlugin_Constraint::VALUE()));
358 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
359 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
361 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
362 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
363 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
365 std::set<AttributePtr>::const_iterator aIt;
366 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
367 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
368 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
369 std::string aRefFeatureKind = aRefFeature->getKind();
370 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
371 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
372 aRefFeatureKind == SketchPlugin_MultiTranslation::ID())
373 theFeaturesToDelete.insert(aRefFeature);
374 else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) {
375 if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) /// TEMPORARY limitaion
376 theFeaturesToDelete.insert(aRefFeature); /// until tangency between arc and line is implemented
378 std::string anAttributeToBeModified;
379 AttributePoint2DPtr aTangentPoint;
380 ObjectPtr aResult1 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->object();
381 ObjectPtr aResult2 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B())->object();
382 if (aResult1.get() && aResult2.get()) {
383 FeaturePtr aCoincidenceFeature = SketchPlugin_ConstraintCoincidence::findCoincidenceFeature
384 (ModelAPI_Feature::feature(aResult1),
385 ModelAPI_Feature::feature(aResult2));
386 aTangentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aCoincidenceFeature);
388 if (aTangentPoint.get()) {
389 FeaturePtr aFeature1 = ModelAPI_Feature::feature(aResult1);
390 std::string anAttributeToBeModified = aFeature1 == aBaseFeature
391 ? SketchPlugin_Constraint::ENTITY_A() : SketchPlugin_Constraint::ENTITY_B();
392 theTangentFeatures[aRefFeature] = std::make_pair(anAttributeToBeModified, aTangentPoint);
395 theFeaturesToDelete.insert(aRefFeature); /// there is not coincident point between tangent constraint
398 else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) {
399 std::string anAttributeToBeModified;
400 AttributePoint2DPtr aCoincidentPoint;
401 AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
402 AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
403 bool isToFeature = false;
404 if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature
405 FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
407 isToFeature = aFeature.get() && aFeature == aBaseFeature;
408 anAttributeToBeModified = anAttrA->id();
410 aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object())
412 isToFeature = aFeature.get() && aFeature == aBaseFeature;
413 anAttributeToBeModified = anAttrB->id();
416 aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
418 if (!isToFeature) { /// coincidence to point on base feature
419 AttributePtr anAttribute;
421 if (!anAttrA->isObject()) {
422 AttributePtr aCurAttribute = anAttrA->attr();
423 if (aCurAttribute.get()) {
424 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
425 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
426 anAttribute = anAttrB->attr();
427 anAttributeToBeModified = anAttrA->id();
431 if (!anAttribute.get() && !anAttrB->isObject()) {
432 AttributePtr aCurAttribute = anAttrB->attr();
433 if (aCurAttribute.get()) {
434 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
435 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
436 anAttribute = anAttrA->attr();
437 anAttributeToBeModified = anAttrB->id();
441 if (anAttribute.get())
442 aCoincidentPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
444 if (aCoincidentPoint.get()) {
446 theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified,
449 //theCoincidenceToPoint[aRefFeature] = std::make_pair(anAttributeToBeModified,
450 // aCoincidentPoint);
453 theFeaturesToDelete.insert(aRefFeature); /// this case should not happen
458 void SketchPlugin_ConstraintSplit::getRefAttributes(const FeaturePtr& theFeature,
459 std::map<AttributePtr, std::list<AttributePtr> >& theRefs)
463 std::list<AttributePtr> aPointAttributes = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
464 std::set<AttributePtr> aPointAttributesSet;
466 std::list<AttributePtr>::const_iterator aPIt = aPointAttributes.begin(), aPLast = aPointAttributes.end();
467 for (; aPIt != aPLast; aPIt++)
468 aPointAttributesSet.insert(*aPIt);
470 const std::set<AttributePtr>& aRefsAttributes = theFeature->data()->refsToMe();
471 std::set<AttributePtr>::const_iterator aIt;
472 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
473 AttributePtr anAttr = (*aIt);
474 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
475 if (anAttrFeature.get() != this &&
476 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
477 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
478 if (!aRefAttr->isObject()) {
479 AttributePtr anAttrInRef = aRefAttr->attr();
480 if (anAttrInRef.get() && aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
481 if (theRefs.find(anAttrInRef) != theRefs.end())
482 theRefs[anAttrInRef].push_back(aRefAttr);
484 std::list<AttributePtr> anAttrList;
485 anAttrList.push_back(aRefAttr);
486 theRefs[anAttrInRef] = anAttrList;
494 void SketchPlugin_ConstraintSplit::updateCoincidenceConstraintsToFeature(
495 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
496 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
497 const std::set<ResultPtr>& theFeatureResults)
499 if (theCoincidenceToFeature.empty())
502 std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
503 aCLast = theCoincidenceToFeature.end();
505 std::cout << std::endl;
506 std::cout << "Coincidences to feature(modified):"<< std::endl;
508 for (; aCIt != aCLast; aCIt++) {
509 FeaturePtr aCoincFeature = aCIt->first;
510 std::string anAttributeId = aCIt->second.first;
511 AttributePoint2DPtr aCoincPoint = aCIt->second.second;
512 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
513 aFCLast = theFurtherCoincidences.end();
514 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aCoincPoint->pnt();
515 AttributePoint2DPtr aFeaturePointAttribute;
516 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
517 AttributePoint2DPtr aFCAttribute = *aFCIt;
518 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
519 aFeaturePointAttribute = aFCAttribute;
521 if (aFeaturePointAttribute.get()) {
522 aCoincFeature->refattr(anAttributeId)->setAttr(aFeaturePointAttribute);
525 /// find feature by shape intersected the point
526 ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
528 if (theFeatureResults.size() > 1) { // try to find point on additional feature
529 ResultPtr anAddtionalResult = *(theFeatureResults.begin()++);
530 GeomShapePtr aShape = anAddtionalResult->shape();
532 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aCoincPoint->pnt();
533 std::shared_ptr<GeomAPI_Pnt> aPoint = sketch()->to3D(aPnt2d->x(), aPnt2d->y());
535 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
536 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPoint, aProjectedPoint))
537 aResultForCoincidence = anAddtionalResult;
539 aCoincFeature->refattr(anAttributeId)->setObject(aResultForCoincidence);
542 std::cout << " -" << getFeatureInfo(aCoincFeature) << std::endl;
547 void SketchPlugin_ConstraintSplit::updateTangentConstraintsToFeature(
548 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theTangentFeatures,
549 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences)
551 if (theTangentFeatures.empty())
554 std::map<FeaturePtr, IdToPointPair>::const_iterator aTIt = theTangentFeatures.begin(),
555 aTLast = theTangentFeatures.end();
557 std::cout << std::endl;
558 std::cout << "Tangencies to feature(modified):"<< std::endl;
560 for (; aTIt != aTLast; aTIt++) {
561 FeaturePtr aTangentFeature = aTIt->first;
562 std::string anAttributeId = aTIt->second.first;
563 AttributePoint2DPtr aTangentPoint = aTIt->second.second;
564 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
565 aFCLast = theFurtherCoincidences.end();
566 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aTangentPoint->pnt();
567 AttributePoint2DPtr aFeaturePointAttribute;
568 /// here we rely on created coincidence between further coincidence point and tangent result
569 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
570 AttributePoint2DPtr aFCAttribute = *aFCIt;
571 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
572 aFeaturePointAttribute = aFCAttribute;
574 if (aFeaturePointAttribute.get()) {
575 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aFeaturePointAttribute->owner());
576 aTangentFeature->refattr(anAttributeId)->setObject(getFeatureResult(aFeature));
579 std::cout << " -" << getFeatureInfo(aTangentFeature) << std::endl;
584 void SketchPlugin_ConstraintSplit::updateRefAttConstraints(
585 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
586 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
589 std::cout << "SketchPlugin_ConstraintSplit::updateRefAttConstraints" << std::endl;
592 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator anIt = theModifiedAttributes.begin(),
593 aLast = theModifiedAttributes.end();
594 for (; anIt != aLast; anIt++) {
595 AttributePtr anAttribute = anIt->first;
597 if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) /// not found in references
599 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
600 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
601 aRLast = aRefAttributes.end();
603 AttributePtr aNewAttribute = anIt->second;
604 for (; aRefIt != aRLast; aRefIt++) {
605 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
606 if (aRefAttr.get()) {
607 aRefAttr->setAttr(aNewAttribute);
609 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
610 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
617 void SketchPlugin_ConstraintSplit::splitLine(FeaturePtr& theSplitFeature,
618 FeaturePtr& theBaseFeatureModified,
619 FeaturePtr& theAfterFeature,
620 std::set<AttributePoint2DPtr>& thePoints,
621 std::set<FeaturePtr>& theCreatedFeatures,
622 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
624 std::set<FeaturePtr> aCreatedFeatures;
625 FeaturePtr aConstraintFeature;
626 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
628 SketchPlugin_Sketch* aSketch = sketch();
632 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
633 data()->attribute(SketchPlugin_Constraint::VALUE()));
634 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
635 std::string aFeatureKind = aBaseFeature->getKind();
636 if (aFeatureKind != SketchPlugin_Line::ID())
639 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
640 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
641 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
642 getFeaturePoints(aStartPointAttrOfBase, anEndPointAttrOfBase);
643 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
644 setError("Error: Feature has no start and end points.");
648 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
650 /// create a split feature
651 theSplitFeature = createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
652 theCreatedFeatures.insert(theSplitFeature);
654 // before split feature
655 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
656 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
657 theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
660 theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
661 /// move end arc point to start of split
664 // after split feature
665 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
667 if (!theBaseFeatureModified.get()) {
668 aFeature = aBaseFeature; ///< use base feature to store all constraints here
669 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
670 aFeature->execute(); // to update result
673 aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
674 theCreatedFeatures.insert(aFeature);
675 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
676 aFeature->attribute(SketchPlugin_Line::END_ID())));
678 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
679 theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
680 aFeature->attribute(SketchPlugin_Line::START_ID()));
681 theCreatedFeatures.insert(aConstraintFeature);
683 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
684 (aFeature->attribute(SketchPlugin_Line::START_ID())));
685 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
686 (aFeature->attribute(SketchPlugin_Line::END_ID())));
688 if (!theBaseFeatureModified.get())
689 theBaseFeatureModified = aFeature;
691 theAfterFeature = aFeature;
694 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
695 (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
696 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
697 theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
699 // base split, that is defined before split feature should be changed at end
700 // (after the after feature creation). Otherwise modified value will be used in after feature
701 // before split feature
702 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
703 /// move end arc point to start of split
704 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()), aFirstPointAttrOfSplit);
705 theBaseFeatureModified->execute(); // to update result
706 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
707 theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
708 theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
709 theCreatedFeatures.insert(aConstraintFeature);
711 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
712 (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
713 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
714 (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
717 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
718 (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
720 // additional constraints between split and base features
721 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
722 getFeatureResult(aBaseFeature),
723 getFeatureResult(theSplitFeature));
724 theCreatedFeatures.insert(aConstraintFeature);
725 if (theAfterFeature.get()) {
726 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
727 getFeatureResult(aBaseFeature),
728 getFeatureResult(theAfterFeature));
729 theCreatedFeatures.insert(aConstraintFeature);
733 void SketchPlugin_ConstraintSplit::splitArc(FeaturePtr& theSplitFeature,
734 FeaturePtr& theBaseFeatureModified,
735 FeaturePtr& theAfterFeature,
736 std::set<AttributePoint2DPtr>& thePoints,
737 std::set<FeaturePtr>& theCreatedFeatures,
738 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
740 std::set<FeaturePtr> aCreatedFeatures;
741 FeaturePtr aConstraintFeature;
742 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
744 SketchPlugin_Sketch* aSketch = sketch();
748 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
749 data()->attribute(SketchPlugin_Constraint::VALUE()));
750 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
751 std::string aFeatureKind = aBaseFeature->getKind();
752 if (aFeatureKind != SketchPlugin_Arc::ID())
755 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
756 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
757 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
758 getFeaturePoints(aStartPointAttrOfBase, anEndPointAttrOfBase);
759 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
760 setError("Error: Feature has no start and end points.");
764 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
765 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
768 theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
769 theCreatedFeatures.insert(theSplitFeature);
771 // before split feature
772 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
773 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
774 theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
777 theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
778 /// move end arc point to start of split
781 // after split feature
782 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
784 if (!theBaseFeatureModified.get()) {
785 aFeature = aBaseFeature; ///< use base feature to store all constraints here
786 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
787 aFeature->execute(); // to update result
790 aFeature = createArcFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
791 theCreatedFeatures.insert(aFeature);
792 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
793 aFeature->attribute(SketchPlugin_Arc::END_ID())));
795 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
796 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
797 aFeature->attribute(SketchPlugin_Arc::START_ID()));
798 theCreatedFeatures.insert(aConstraintFeature);
800 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
801 (aFeature->attribute(SketchPlugin_Arc::START_ID())));
802 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
803 (aFeature->attribute(SketchPlugin_Arc::END_ID())));
805 if (!theBaseFeatureModified.get())
806 theBaseFeatureModified = aFeature;
808 theAfterFeature = aFeature;
811 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
812 (theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
813 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
814 theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
816 // base split, that is defined before split feature should be changed at end
817 // (after the after feature creation). Otherwise modified value will be used in after feature
818 // before split feature
819 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
820 /// move end arc point to start of split
821 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()), aFirstPointAttrOfSplit);
822 theBaseFeatureModified->execute(); // to update result
823 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
824 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
825 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
826 theCreatedFeatures.insert(aConstraintFeature);
828 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
829 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
830 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
831 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
834 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
835 (theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
837 // additional constraints between split and base features
838 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
839 getFeatureResult(aBaseFeature),
840 getFeatureResult(theSplitFeature));
841 theCreatedFeatures.insert(aConstraintFeature);
842 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
843 getFeatureResult(theSplitFeature),
844 getFeatureResult(aBaseFeature));
845 theCreatedFeatures.insert(aConstraintFeature);
846 if (theAfterFeature.get()) {
847 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
848 getFeatureResult(aBaseFeature),
849 getFeatureResult(theAfterFeature));
850 theCreatedFeatures.insert(aConstraintFeature);
851 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
852 getFeatureResult(theSplitFeature),
853 getFeatureResult(theAfterFeature));
854 theCreatedFeatures.insert(aConstraintFeature);
858 void SketchPlugin_ConstraintSplit::splitCircle(FeaturePtr& theSplitFeature,
859 FeaturePtr& theBaseFeatureModified,
860 FeaturePtr& theAfterFeature,
861 std::set<AttributePoint2DPtr>& thePoints,
862 std::set<FeaturePtr>& theCreatedFeatures,
863 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
865 std::set<FeaturePtr> aCreatedFeatures;
866 FeaturePtr aConstraintFeature;
867 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
869 SketchPlugin_Sketch* aSketch = sketch();
873 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
874 data()->attribute(SketchPlugin_Constraint::VALUE()));
875 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
876 std::string aFeatureKind = aBaseFeature->getKind();
877 if (aFeatureKind != SketchPlugin_Circle::ID())
880 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
881 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
884 theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
885 bool aSplitReversed = std::dynamic_pointer_cast<SketchPlugin_Arc>(theSplitFeature)->isReversed();
886 theCreatedFeatures.insert(theSplitFeature);
888 /// base feature is a left part of the circle
889 theBaseFeatureModified = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
890 std::dynamic_pointer_cast<SketchPlugin_Arc>(theBaseFeatureModified)->setReversed(!aSplitReversed);
891 theBaseFeatureModified->execute();
893 theModifiedAttributes.insert(std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
894 theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
896 theCreatedFeatures.insert(theBaseFeatureModified);
898 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
899 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
900 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
901 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
903 // additional constraints between split and base features
904 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
905 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
906 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()));
907 theCreatedFeatures.insert(aConstraintFeature);
908 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
909 theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()),
910 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
911 theCreatedFeatures.insert(aConstraintFeature);
913 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
914 getFeatureResult(theSplitFeature),
915 getFeatureResult(theBaseFeatureModified));
916 theCreatedFeatures.insert(aConstraintFeature);
919 void SketchPlugin_ConstraintSplit::arrangePointsOnLine(
920 const AttributePoint2DPtr& theStartPointAttr,
921 const AttributePoint2DPtr& theEndPointAttr,
922 AttributePoint2DPtr& theFirstPointAttr,
923 AttributePoint2DPtr& theLastPointAttr) const
925 // if first point is closer to last point, swap first and last values
926 if (theStartPointAttr->pnt()->distance(theFirstPointAttr->pnt()) >
927 theStartPointAttr->pnt()->distance(theLastPointAttr->pnt())) {
928 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
929 theFirstPointAttr = theLastPointAttr;
930 theLastPointAttr = aTmpPoint;
934 void SketchPlugin_ConstraintSplit::arrangePointsOnArc(
935 const FeaturePtr& theArc,
936 const std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
937 const std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr,
938 std::shared_ptr<GeomDataAPI_Point2D>& theFirstPointAttr,
939 std::shared_ptr<GeomDataAPI_Point2D>& theSecondPointAttr) const
941 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
942 theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
943 bool isReversed = theArc->boolean(SketchPlugin_Arc::INVERSED_ID())->value();
945 // collect directions to each point
946 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
947 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
948 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
949 new GeomAPI_Dir2d(theFirstPointAttr->pnt()->xy()->decreased(aCenter->xy())));
950 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
951 new GeomAPI_Dir2d(theSecondPointAttr->pnt()->xy()->decreased(aCenter->xy())));
953 // sort points by their angular values
954 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
955 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
956 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
957 if (isReversed == (aFirstPtAngle > 0.))
958 aFirstPtAngle += aPeriod;
959 if (isReversed == (aSecondPtAngle > 0.))
960 aSecondPtAngle += aPeriod;
962 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
963 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
964 theFirstPointAttr = theSecondPointAttr;
965 theSecondPointAttr = aTmpPoint;
969 void SketchPlugin_ConstraintSplit::fillAttribute(const AttributePtr& theModifiedAttribute,
970 const AttributePtr& theSourceAttribute)
972 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
973 theModifiedAttribute);
974 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
977 if (aModifiedAttribute.get() && aSourceAttribute.get())
978 aModifiedAttribute->setValue(aSourceAttribute->pnt());
981 FeaturePtr SketchPlugin_ConstraintSplit::createLineFeature(const FeaturePtr& theBaseFeature,
982 const AttributePtr& theFirstPointAttr,
983 const AttributePtr& theSecondPointAttr)
986 SketchPlugin_Sketch* aSketch = sketch();
987 if (!aSketch || !theBaseFeature.get())
990 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
992 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPointAttr);
993 fillAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPointAttr);
994 aFeature->execute(); // to obtain result
999 FeaturePtr SketchPlugin_ConstraintSplit::createArcFeature(const FeaturePtr& theBaseFeature,
1000 const AttributePtr& theFirstPointAttr,
1001 const AttributePtr& theSecondPointAttr)
1003 FeaturePtr aFeature;
1004 SketchPlugin_Sketch* aSketch = sketch();
1005 if (!aSketch || !theBaseFeature.get())
1008 std::string aCenterAttributeId;
1009 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
1010 aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
1011 else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
1012 aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
1014 if (aCenterAttributeId.empty())
1017 aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
1018 // update fillet arc: make the arc correct for sure, so, it is not needed to process the "attribute updated"
1019 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1020 aFeature->data()->blockSendAttributeUpdated(true);
1022 aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
1023 SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
1025 fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1026 theBaseFeature->attribute(aCenterAttributeId));
1027 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
1028 fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
1030 /// fill referersed state of created arc as it is on the base arc
1031 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
1032 bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->value();
1033 aFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(aReversed);
1035 aFeature->data()->blockSendAttributeUpdated(false);
1036 aFeature->execute(); // to obtain result
1041 FeaturePtr SketchPlugin_ConstraintSplit::createConstraint(const std::string& theConstraintId,
1042 const AttributePtr& theFirstAttribute,
1043 const AttributePtr& theSecondAttribute)
1045 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1046 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1047 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1048 aRefAttr->setAttr(theFirstAttribute);
1050 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1051 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1052 aRefAttr->setAttr(theSecondAttribute);
1057 FeaturePtr SketchPlugin_ConstraintSplit::createConstraintForObjects(const std::string& theConstraintId,
1058 const ObjectPtr& theFirstObject,
1059 const ObjectPtr& theSecondObject)
1061 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1062 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1063 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1064 aRefAttr->setObject(theFirstObject);
1066 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1067 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1068 aRefAttr->setObject(theSecondObject);
1073 std::shared_ptr<ModelAPI_Result> SketchPlugin_ConstraintSplit::getFeatureResult(
1074 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1076 std::shared_ptr<ModelAPI_Result> aResult;
1078 std::string aFeatureKind = theFeature->getKind();
1079 if (aFeatureKind == SketchPlugin_Line::ID())
1080 aResult = theFeature->firstResult();
1081 else if (aFeatureKind == SketchPlugin_Arc::ID())
1082 aResult = theFeature->lastResult();
1083 else if (aFeatureKind == SketchPlugin_Circle::ID())
1084 aResult = theFeature->lastResult();
1089 std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_ConstraintSplit::getEdgeAttributes(
1090 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1092 std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
1094 std::string aFeatureKind = theFeature->getKind();
1095 if (aFeatureKind == SketchPlugin_Line::ID()) {
1096 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::START_ID()));
1097 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::END_ID()));
1099 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
1100 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
1101 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
1103 else if (aFeatureKind == SketchPlugin_Circle::ID()) {
1106 return anAttributes;
1110 std::string SketchPlugin_ConstraintSplit::getFeatureInfo(
1111 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1112 const bool isUseAttributesInfo)
1115 if (!theFeature.get()) {
1119 if (theFeature->data()->isValid())
1120 anInfo.append(theFeature->data()->name().c_str());
1122 if (isUseAttributesInfo) {
1123 std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
1124 getEdgeAttributes(theFeature));
1125 if (!aPointsInfo.empty()) { /// processing of feature with point 2d attributes, like line, arc, circle
1128 anInfo += aPointsInfo;
1130 else { /// process constraint coincidence, find points in ref attr attributes
1131 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
1132 ModelAPI_AttributeRefAttr::typeId());
1133 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
1134 std::string anAttributesInfo;
1135 for(; anIt != aLast; anIt++) {
1136 if (!anAttributesInfo.empty()) {
1137 anAttributesInfo.append(", ");
1138 anAttributesInfo += "\n";
1140 AttributePtr anAttr = *anIt;
1141 std::string aValue = "not defined";
1142 std::string aType = anAttr->attributeType();
1143 if (aType == ModelAPI_AttributeRefAttr::typeId()) {
1144 std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
1145 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
1146 if (aRefAttr.get()) {
1147 if (aRefAttr->isObject()) {
1148 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1149 aValue = "<object:>" + getFeatureInfo(aFeature, false);
1152 AttributePtr anAttribute = aRefAttr->attr();
1153 if (anAttribute.get()) {
1154 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
1155 aValue = "<attr:>" + ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute) +
1156 " [" + getFeatureInfo(aFeature, false) + "]";
1161 anAttributesInfo.append(" " + anAttr->id() + ": " + aValue);
1163 if (!anAttributesInfo.empty())
1164 anInfo = anInfo + "\n" + anAttributesInfo;