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 attributes of base 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(",");
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 << aPointAttr->id().c_str() << ": " << "[" << aRefAttributes.size() << "] " << aRefsInfo << std::endl;
183 std::cout << std::endl;
184 std::cout << "---- SPLIT ----" << std::endl;
185 std::cout << std::endl;
188 std::string aFeatureKind = aBaseFeature->getKind();
189 FeaturePtr aSplitFeature, anAfterFeature;
190 std::set<AttributePoint2DPtr> aFurtherCoincidences;
191 std::set<FeaturePtr> aCreatedFeatures;
192 std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
193 if (aFeatureKind == SketchPlugin_Line::ID())
194 splitLine(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
195 aModifiedAttributes);
196 else if (aFeatureKind == SketchPlugin_Arc::ID())
197 splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
198 aModifiedAttributes);
199 if (aFeatureKind == SketchPlugin_Circle::ID()) {
200 FeaturePtr aCircleFeature = aBaseFeature;
201 splitCircle(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences, aCreatedFeatures,
202 aModifiedAttributes);
203 aFeaturesToDelete.insert(aCircleFeature);
204 aBaseObjectAttr->setObject(ResultPtr()); // as circle is removed, temporary fill this attribute
208 std::cout << "---- OUT PARAMETERS ----" << std::endl;
209 std::cout << "Base modified feature:" << getFeatureInfo(aBaseFeature) << std::endl;
210 std::cout << "Split feature:" << getFeatureInfo(aSplitFeature) << std::endl;
211 std::cout << "After feature:" << getFeatureInfo(anAfterFeature) << std::endl;
212 std::cout << std::endl;
214 std::cout << "Created features by split:[" << aCreatedFeatures.size() << "]" << std::endl;
215 std::set<FeaturePtr>::const_iterator aFIt = aCreatedFeatures.begin(),
216 aFLast = aCreatedFeatures.end();
217 for (; aFIt != aFLast; aFIt++) {
218 std::cout << getFeatureInfo(*aFIt) << std::endl;
220 std::cout << std::endl;
222 std::cout << "Attributes for further Coincidences:" << std::endl;
223 std::set<AttributePoint2DPtr>::const_iterator anIt = aFurtherCoincidences.begin(),
224 aLast = aFurtherCoincidences.end();
225 for (; anIt != aLast; anIt++) {
226 AttributePtr anAttribute = *anIt;
227 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
228 std::cout << ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute)
229 << " [" << getFeatureInfo(aFeature, false) << "]" << std::endl;
232 std::cout << "Modifed attributes (constraints to attributes are moved here):" << std::endl;
233 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator aPIt = aModifiedAttributes.begin(),
234 aPLast = aModifiedAttributes.end();
235 std::string aResInfo;
236 for (; aPIt != aPLast; aPIt++) {
237 if (!aResInfo.empty())
240 std::pair<AttributePtr, AttributePtr> aPair = *aPIt;
242 AttributePtr anAttr = aPair.first;
243 aResInfo.append(anAttr->id());
244 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->owner());
245 aResInfo.append("(" + aFeature->name() + ") ");
247 aResInfo.append(" - is modified to - ");
249 anAttr = aPair.second;
250 aResInfo.append(anAttr->id());
251 aFeature = ModelAPI_Feature::feature(anAttr->owner());
252 aResInfo.append("(" + aFeature->name() + ") ");
254 std::cout << aResInfo << std::endl;
257 std::set<ResultPtr> aFeatureResults;
258 aFeatureResults.insert(getFeatureResult(aBaseFeature));
259 if (anAfterFeature.get() && anAfterFeature != aBaseFeature)
260 aFeatureResults.insert(getFeatureResult(anAfterFeature));
262 // coincidence to feature
263 updateCoincidenceConstraintsToFeature(aCoincidenceToFeature, aFurtherCoincidences,
265 // coincidence to points
266 //updateCoincidenceConstraintsToFeature(aCoincidenceToPoint, aFurtherCoincidences,
267 // std::set<ResultPtr>());
269 updateTangentConstraintsToFeature(aTangentFeatures, aFurtherCoincidences);
271 updateRefAttConstraints(aBaseRefAttributes, aModifiedAttributes);
273 // delete constraints
275 std::cout << "remove features and references:" << std::endl;
276 std::set<FeaturePtr>::const_iterator aDIt = aFeaturesToDelete.begin(),
277 aDLast = aFeaturesToDelete.end();
278 for (; aDIt != aDLast; aDIt++) {
279 std::cout << getFeatureInfo(*aDIt, false) << std::endl;
280 std::cout << std::endl;
283 ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToDelete);
285 // Send events to update the sub-features by the solver.
286 if(isUpdateFlushed) {
287 Events_Loop::loop()->setFlushed(anUpdateEvent, true);
291 std::cout << "SKETCH FEATURES (after split) [" << aSketch->numberOfSubs() << "]:" << std::endl;
292 for (int i = 0, aNbSubs = aSketch->numberOfSubs(); i < aNbSubs; i++) {
293 std::cout << getFeatureInfo(aSketch->subFeature(i), false) << std::endl;
298 bool SketchPlugin_ConstraintSplit::isMacro() const
303 std::shared_ptr<GeomDataAPI_Point2D> SketchPlugin_ConstraintSplit::getPointOfRefAttr(
304 const AttributePtr& theAttribute)
306 AttributePoint2DPtr aPointAttribute;
308 if (theAttribute->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
309 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
310 if (aRefAttr.get() && aRefAttr->isInitialized()) {
311 AttributePtr anAttribute = aRefAttr->attr();
312 if (anAttribute.get() && anAttribute->attributeType() == GeomDataAPI_Point2D::typeId())
313 aPointAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
316 return aPointAttribute;
319 void SketchPlugin_ConstraintSplit::getFeaturePoints(AttributePoint2DPtr& theStartPointAttr,
320 AttributePoint2DPtr& theEndPointAttr)
322 AttributePoint2DPtr aPointAttribute;
324 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
325 data()->attribute(SketchPlugin_Constraint::VALUE()));
326 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
328 std::string aFeatureKind = aBaseFeature->getKind();
329 std::string aStartAttributeName, anEndAttributeName;
330 if (aFeatureKind == SketchPlugin_Line::ID()) {
331 aStartAttributeName = SketchPlugin_Line::START_ID();
332 anEndAttributeName = SketchPlugin_Line::END_ID();
334 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
335 aStartAttributeName = SketchPlugin_Arc::START_ID();
336 anEndAttributeName = SketchPlugin_Arc::END_ID();
338 if (!aStartAttributeName.empty() && !anEndAttributeName.empty()) {
339 theStartPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
340 aBaseFeature->attribute(aStartAttributeName));
341 theEndPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
342 aBaseFeature->attribute(anEndAttributeName));
346 void SketchPlugin_ConstraintSplit::getConstraints(std::set<FeaturePtr>& theFeaturesToDelete,
347 std::map<FeaturePtr, IdToPointPair>& theTangentFeatures,
348 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToFeature/*,
349 std::map<FeaturePtr, IdToPointPair>& theCoincidenceToPoint*/)
351 std::shared_ptr<ModelAPI_Data> aData = data();
353 // Check the base objects are initialized.
354 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
355 aData->attribute(SketchPlugin_Constraint::VALUE()));
356 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
357 ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
359 std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
360 std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
361 aRefsList.insert(aFRefsList.begin(), aFRefsList.end());
363 std::set<AttributePtr>::const_iterator aIt;
364 for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
365 std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
366 FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
367 std::string aRefFeatureKind = aRefFeature->getKind();
368 if (aRefFeatureKind == SketchPlugin_ConstraintMirror::ID() ||
369 aRefFeatureKind == SketchPlugin_MultiRotation::ID() ||
370 aRefFeatureKind == SketchPlugin_MultiTranslation::ID())
371 theFeaturesToDelete.insert(aRefFeature);
372 else if (aRefFeatureKind == SketchPlugin_ConstraintTangent::ID()) {
373 if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) /// TEMPORARY limitaion
374 theFeaturesToDelete.insert(aRefFeature); /// until tangency between arc and line is implemented
376 std::string anAttributeToBeModified;
377 AttributePoint2DPtr aTangentPoint;
378 ObjectPtr aResult1 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A())->object();
379 ObjectPtr aResult2 = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B())->object();
380 if (aResult1.get() && aResult2.get()) {
381 FeaturePtr aCoincidenceFeature = SketchPlugin_ConstraintCoincidence::findCoincidenceFeature
382 (ModelAPI_Feature::feature(aResult1),
383 ModelAPI_Feature::feature(aResult2));
384 // get the point not lying on the splitting feature
385 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; ++i) {
386 AttributeRefAttrPtr aRefAttr = aCoincidenceFeature->refattr(ATTRIBUTE(i));
387 if (!aRefAttr || aRefAttr->isObject())
389 AttributePoint2DPtr aPoint =
390 std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttr->attr());
393 if (aPoint->owner() != aBaseFeature) {
394 aTangentPoint = aPoint;
399 if (aTangentPoint.get()) {
400 FeaturePtr aFeature1 = ModelAPI_Feature::feature(aResult1);
401 std::string anAttributeToBeModified = aFeature1 == aBaseFeature
402 ? SketchPlugin_Constraint::ENTITY_A() : SketchPlugin_Constraint::ENTITY_B();
403 theTangentFeatures[aRefFeature] = std::make_pair(anAttributeToBeModified, aTangentPoint);
406 theFeaturesToDelete.insert(aRefFeature); /// there is not coincident point between tangent constraint
409 else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) {
410 std::string anAttributeToBeModified;
411 AttributePoint2DPtr aCoincidentPoint;
412 AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
413 AttributeRefAttrPtr anAttrB = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_B());
414 bool isToFeature = false;
415 if (anAttrA->isObject() || anAttrB->isObject()) { /// coincidence to base feature
416 FeaturePtr aFeature = anAttrA->isObject() ? ModelAPI_Feature::feature(anAttrA->object())
418 isToFeature = aFeature.get() && aFeature == aBaseFeature;
419 anAttributeToBeModified = anAttrA->id();
421 aFeature = anAttrB->isObject() ? ModelAPI_Feature::feature(anAttrB->object())
423 isToFeature = aFeature.get() && aFeature == aBaseFeature;
424 anAttributeToBeModified = anAttrB->id();
427 aCoincidentPoint = SketchPlugin_ConstraintCoincidence::getPoint(aRefFeature);
429 if (!isToFeature) { /// coincidence to point on base feature
430 AttributePtr anAttribute;
432 if (!anAttrA->isObject()) {
433 AttributePtr aCurAttribute = anAttrA->attr();
434 if (aCurAttribute.get()) {
435 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
436 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
437 anAttribute = anAttrB->attr();
438 anAttributeToBeModified = anAttrA->id();
442 if (!anAttribute.get() && !anAttrB->isObject()) {
443 AttributePtr aCurAttribute = anAttrB->attr();
444 if (aCurAttribute.get()) {
445 FeaturePtr aCurFeature = ModelAPI_Feature::feature(aCurAttribute->owner());
446 if (aCurFeature.get() && aCurFeature == aBaseFeature) {
447 anAttribute = anAttrA->attr();
448 anAttributeToBeModified = anAttrB->id();
452 if (anAttribute.get())
453 aCoincidentPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttribute);
455 if (aCoincidentPoint.get()) {
457 theCoincidenceToFeature[aRefFeature] = std::make_pair(anAttributeToBeModified,
460 //theCoincidenceToPoint[aRefFeature] = std::make_pair(anAttributeToBeModified,
461 // aCoincidentPoint);
464 theFeaturesToDelete.insert(aRefFeature); /// this case should not happen
469 void SketchPlugin_ConstraintSplit::getRefAttributes(const FeaturePtr& theFeature,
470 std::map<AttributePtr, std::list<AttributePtr> >& theRefs)
474 std::list<AttributePtr> aPointAttributes = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
475 std::set<AttributePtr> aPointAttributesSet;
477 std::list<AttributePtr>::const_iterator aPIt = aPointAttributes.begin(), aPLast = aPointAttributes.end();
478 for (; aPIt != aPLast; aPIt++)
479 aPointAttributesSet.insert(*aPIt);
481 const std::set<AttributePtr>& aRefsAttributes = theFeature->data()->refsToMe();
482 std::set<AttributePtr>::const_iterator aIt;
483 for (aIt = aRefsAttributes.cbegin(); aIt != aRefsAttributes.cend(); ++aIt) {
484 AttributePtr anAttr = (*aIt);
485 FeaturePtr anAttrFeature = ModelAPI_Feature::feature(anAttr->owner());
486 if (anAttrFeature.get() != this &&
487 anAttr.get() && anAttr->attributeType() == ModelAPI_AttributeRefAttr::typeId()) {
488 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
489 if (!aRefAttr->isObject()) {
490 AttributePtr anAttrInRef = aRefAttr->attr();
491 if (anAttrInRef.get() && aPointAttributesSet.find(anAttrInRef) != aPointAttributesSet.end()) {
492 if (theRefs.find(anAttrInRef) != theRefs.end())
493 theRefs[anAttrInRef].push_back(aRefAttr);
495 std::list<AttributePtr> anAttrList;
496 anAttrList.push_back(aRefAttr);
497 theRefs[anAttrInRef] = anAttrList;
505 void SketchPlugin_ConstraintSplit::updateCoincidenceConstraintsToFeature(
506 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theCoincidenceToFeature,
507 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences,
508 const std::set<ResultPtr>& theFeatureResults)
510 if (theCoincidenceToFeature.empty())
513 std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
514 aCLast = theCoincidenceToFeature.end();
516 std::cout << std::endl;
517 std::cout << "Coincidences to feature(modified):"<< std::endl;
519 for (; aCIt != aCLast; aCIt++) {
520 FeaturePtr aCoincFeature = aCIt->first;
521 std::string anAttributeId = aCIt->second.first;
522 AttributePoint2DPtr aCoincPoint = aCIt->second.second;
523 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
524 aFCLast = theFurtherCoincidences.end();
525 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aCoincPoint->pnt();
526 AttributePoint2DPtr aFeaturePointAttribute;
527 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
528 AttributePoint2DPtr aFCAttribute = *aFCIt;
529 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
530 aFeaturePointAttribute = aFCAttribute;
532 if (aFeaturePointAttribute.get()) {
533 aCoincFeature->refattr(anAttributeId)->setObject(ResultPtr());
534 aCoincFeature->refattr(anAttributeId)->setAttr(aFeaturePointAttribute);
537 /// find feature by shape intersected the point
538 ResultPtr aResultForCoincidence = *(theFeatureResults.begin());
540 if (theFeatureResults.size() > 1) { // try to find point on additional feature
541 ResultPtr anAddtionalResult = *(theFeatureResults.begin()++);
542 GeomShapePtr aShape = anAddtionalResult->shape();
544 std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = aCoincPoint->pnt();
545 std::shared_ptr<GeomAPI_Pnt> aPoint = sketch()->to3D(aPnt2d->x(), aPnt2d->y());
547 std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
548 if (ModelGeomAlgo_Point2D::isPointOnEdge(aShape, aPoint, aProjectedPoint))
549 aResultForCoincidence = anAddtionalResult;
551 aCoincFeature->refattr(anAttributeId)->setObject(aResultForCoincidence);
554 std::cout << " -" << getFeatureInfo(aCoincFeature) << std::endl;
559 void SketchPlugin_ConstraintSplit::updateTangentConstraintsToFeature(
560 const std::map<std::shared_ptr<ModelAPI_Feature>, IdToPointPair>& theTangentFeatures,
561 const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theFurtherCoincidences)
563 if (theTangentFeatures.empty())
566 std::map<FeaturePtr, IdToPointPair>::const_iterator aTIt = theTangentFeatures.begin(),
567 aTLast = theTangentFeatures.end();
569 std::cout << std::endl;
570 std::cout << "Tangencies to feature(modified):"<< std::endl;
572 for (; aTIt != aTLast; aTIt++) {
573 FeaturePtr aTangentFeature = aTIt->first;
574 std::string anAttributeId = aTIt->second.first;
575 AttributePoint2DPtr aTangentPoint = aTIt->second.second;
576 std::set<AttributePoint2DPtr>::const_iterator aFCIt = theFurtherCoincidences.begin(),
577 aFCLast = theFurtherCoincidences.end();
578 std::shared_ptr<GeomAPI_Pnt2d> aCoincPnt = aTangentPoint->pnt();
579 AttributePoint2DPtr aFeaturePointAttribute;
580 /// here we rely on created coincidence between further coincidence point and tangent result
581 for (; aFCIt != aFCLast && !aFeaturePointAttribute.get(); aFCIt++) {
582 AttributePoint2DPtr aFCAttribute = *aFCIt;
583 if (aCoincPnt->isEqual(aFCAttribute->pnt()))
584 aFeaturePointAttribute = aFCAttribute;
586 if (aFeaturePointAttribute.get()) {
587 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aFeaturePointAttribute->owner());
588 aTangentFeature->refattr(anAttributeId)->setObject(getFeatureResult(aFeature));
591 std::cout << " -" << getFeatureInfo(aTangentFeature) << std::endl;
596 void SketchPlugin_ConstraintSplit::updateRefAttConstraints(
597 const std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
598 const std::set<std::pair<AttributePtr, AttributePtr> >& theModifiedAttributes)
601 std::cout << "SketchPlugin_ConstraintSplit::updateRefAttConstraints" << std::endl;
604 std::set<std::pair<AttributePtr, AttributePtr> >::const_iterator anIt = theModifiedAttributes.begin(),
605 aLast = theModifiedAttributes.end();
606 for (; anIt != aLast; anIt++) {
607 AttributePtr anAttribute = anIt->first;
609 if (theBaseRefAttributes.find(anAttribute) == theBaseRefAttributes.end()) /// not found in references
611 std::list<AttributePtr> aRefAttributes = theBaseRefAttributes.at(anAttribute);
612 std::list<AttributePtr>::const_iterator aRefIt = aRefAttributes.begin(),
613 aRLast = aRefAttributes.end();
615 AttributePtr aNewAttribute = anIt->second;
616 for (; aRefIt != aRLast; aRefIt++) {
617 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*aRefIt);
618 if (aRefAttr.get()) {
619 aRefAttr->setAttr(aNewAttribute);
621 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->owner());
622 std::cout << " -" << getFeatureInfo(aFeature) << std::endl;
629 void SketchPlugin_ConstraintSplit::splitLine(FeaturePtr& theSplitFeature,
630 FeaturePtr& theBaseFeatureModified,
631 FeaturePtr& theAfterFeature,
632 std::set<AttributePoint2DPtr>& thePoints,
633 std::set<FeaturePtr>& theCreatedFeatures,
634 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
636 std::set<FeaturePtr> aCreatedFeatures;
637 FeaturePtr aConstraintFeature;
638 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
640 SketchPlugin_Sketch* aSketch = sketch();
644 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
645 data()->attribute(SketchPlugin_Constraint::VALUE()));
646 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
647 std::string aFeatureKind = aBaseFeature->getKind();
648 if (aFeatureKind != SketchPlugin_Line::ID())
651 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
652 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
653 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
654 getFeaturePoints(aStartPointAttrOfBase, anEndPointAttrOfBase);
655 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
656 setError("Error: Feature has no start and end points.");
660 arrangePointsOnLine(aStartPointAttrOfBase, anEndPointAttrOfBase, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
663 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
664 std::cout << "Start point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
665 std::cout << "1st point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
666 std::cout << "2nd point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
667 std::cout << "End point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
670 /// create a split feature
671 theSplitFeature = createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
672 theCreatedFeatures.insert(theSplitFeature);
674 // before split feature
675 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
676 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
677 theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
680 theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
681 /// move end arc point to start of split
684 // after split feature
685 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
687 if (!theBaseFeatureModified.get()) {
688 aFeature = aBaseFeature; ///< use base feature to store all constraints here
689 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), aSecondPointAttrOfSplit);
690 aFeature->execute(); // to update result
693 aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
694 theCreatedFeatures.insert(aFeature);
695 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
696 aFeature->attribute(SketchPlugin_Line::END_ID())));
698 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
699 theSplitFeature->attribute(SketchPlugin_Line::END_ID()),
700 aFeature->attribute(SketchPlugin_Line::START_ID()));
701 theCreatedFeatures.insert(aConstraintFeature);
703 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
704 (aFeature->attribute(SketchPlugin_Line::START_ID())));
705 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
706 (aFeature->attribute(SketchPlugin_Line::END_ID())));
708 if (!theBaseFeatureModified.get())
709 theBaseFeatureModified = aFeature;
711 theAfterFeature = aFeature;
714 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
715 (theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
716 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
717 theSplitFeature->attribute(SketchPlugin_Line::END_ID())));
719 // base split, that is defined before split feature should be changed at end
720 // (after the after feature creation). Otherwise modified value will be used in after feature
721 // before split feature
722 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
723 /// move end arc point to start of split
724 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()), aFirstPointAttrOfSplit);
725 theBaseFeatureModified->execute(); // to update result
726 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
727 theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID()),
728 theSplitFeature->attribute(SketchPlugin_Line::START_ID()));
729 theCreatedFeatures.insert(aConstraintFeature);
731 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
732 (theBaseFeatureModified->attribute(SketchPlugin_Line::START_ID())));
733 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
734 (theBaseFeatureModified->attribute(SketchPlugin_Line::END_ID())));
737 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
738 (theSplitFeature->attribute(SketchPlugin_Line::START_ID())));
740 // additional constraints between split and base features
741 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
742 getFeatureResult(aBaseFeature),
743 getFeatureResult(theSplitFeature));
744 theCreatedFeatures.insert(aConstraintFeature);
745 if (theAfterFeature.get()) {
746 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintParallel::ID(),
747 getFeatureResult(aBaseFeature),
748 getFeatureResult(theAfterFeature));
749 theCreatedFeatures.insert(aConstraintFeature);
753 void SketchPlugin_ConstraintSplit::splitArc(FeaturePtr& theSplitFeature,
754 FeaturePtr& theBaseFeatureModified,
755 FeaturePtr& theAfterFeature,
756 std::set<AttributePoint2DPtr>& thePoints,
757 std::set<FeaturePtr>& theCreatedFeatures,
758 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
760 std::set<FeaturePtr> aCreatedFeatures;
761 FeaturePtr aConstraintFeature;
762 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
764 SketchPlugin_Sketch* aSketch = sketch();
768 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
769 data()->attribute(SketchPlugin_Constraint::VALUE()));
770 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
771 std::string aFeatureKind = aBaseFeature->getKind();
772 if (aFeatureKind != SketchPlugin_Arc::ID())
775 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
776 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
777 AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
778 getFeaturePoints(aStartPointAttrOfBase, anEndPointAttrOfBase);
779 if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
780 setError("Error: Feature has no start and end points.");
784 // manually change type of arc to avoid incorrect self-constrainting of the tangent arc
785 aBaseFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
786 SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
788 arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
789 aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
791 std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
792 std::cout << "Start point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
793 std::cout << "1st point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
794 std::cout << "2nd point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
795 std::cout << "End point: " << ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
799 theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
800 theCreatedFeatures.insert(theSplitFeature);
802 // before split feature
803 if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
804 theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
805 theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
808 theBaseFeatureModified = aBaseFeature; ///< use base feature to store all constraints here
809 /// move end arc point to start of split
812 // after split feature
813 if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
815 if (!theBaseFeatureModified.get()) {
816 aFeature = aBaseFeature; ///< use base feature to store all constraints here
817 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
818 aFeature->execute(); // to update result
821 aFeature = createArcFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
822 theCreatedFeatures.insert(aFeature);
823 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
824 aFeature->attribute(SketchPlugin_Arc::END_ID())));
826 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
827 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()),
828 aFeature->attribute(SketchPlugin_Arc::START_ID()));
829 theCreatedFeatures.insert(aConstraintFeature);
831 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
832 (aFeature->attribute(SketchPlugin_Arc::START_ID())));
833 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
834 (aFeature->attribute(SketchPlugin_Arc::END_ID())));
836 if (!theBaseFeatureModified.get())
837 theBaseFeatureModified = aFeature;
839 theAfterFeature = aFeature;
842 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
843 (theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
844 theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
845 theSplitFeature->attribute(SketchPlugin_Arc::END_ID())));
847 // base split, that is defined before split feature should be changed at end
848 // (after the after feature creation). Otherwise modified value will be used in after feature
849 // before split feature
850 if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
851 /// move end arc point to start of split
852 fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()), aFirstPointAttrOfSplit);
853 theBaseFeatureModified->execute(); // to update result
854 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
855 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
856 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
857 theCreatedFeatures.insert(aConstraintFeature);
859 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
860 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
861 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
862 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
865 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
866 (theSplitFeature->attribute(SketchPlugin_Arc::START_ID())));
868 // additional constraints between split and base features
869 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
870 getFeatureResult(aBaseFeature),
871 getFeatureResult(theSplitFeature));
872 theCreatedFeatures.insert(aConstraintFeature);
873 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
874 getFeatureResult(theSplitFeature),
875 getFeatureResult(aBaseFeature));
876 theCreatedFeatures.insert(aConstraintFeature);
877 if (theAfterFeature.get()) {
878 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintEqual::ID(),
879 getFeatureResult(aBaseFeature),
880 getFeatureResult(theAfterFeature));
881 theCreatedFeatures.insert(aConstraintFeature);
882 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
883 getFeatureResult(theSplitFeature),
884 getFeatureResult(theAfterFeature));
885 theCreatedFeatures.insert(aConstraintFeature);
889 void SketchPlugin_ConstraintSplit::splitCircle(FeaturePtr& theSplitFeature,
890 FeaturePtr& theBaseFeatureModified,
891 FeaturePtr& theAfterFeature,
892 std::set<AttributePoint2DPtr>& thePoints,
893 std::set<FeaturePtr>& theCreatedFeatures,
894 std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
896 std::set<FeaturePtr> aCreatedFeatures;
897 FeaturePtr aConstraintFeature;
898 theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
900 SketchPlugin_Sketch* aSketch = sketch();
904 AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
905 data()->attribute(SketchPlugin_Constraint::VALUE()));
906 FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
907 std::string aFeatureKind = aBaseFeature->getKind();
908 if (aFeatureKind != SketchPlugin_Circle::ID())
911 AttributePoint2DPtr aFirstPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_A()));
912 AttributePoint2DPtr aSecondPointAttrOfSplit = getPointOfRefAttr(data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
915 theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
916 bool aSplitReversed = std::dynamic_pointer_cast<SketchPlugin_Arc>(theSplitFeature)->isReversed();
917 theCreatedFeatures.insert(theSplitFeature);
919 /// base feature is a left part of the circle
920 theBaseFeatureModified = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
921 std::dynamic_pointer_cast<SketchPlugin_Arc>(theBaseFeatureModified)->setReversed(!aSplitReversed);
922 theBaseFeatureModified->execute();
924 theModifiedAttributes.insert(std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
925 theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
927 theCreatedFeatures.insert(theBaseFeatureModified);
929 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
930 (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
931 thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
932 (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
934 // additional constraints between split and base features
935 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
936 theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
937 theSplitFeature->attribute(SketchPlugin_Arc::END_ID()));
938 theCreatedFeatures.insert(aConstraintFeature);
939 aConstraintFeature = createConstraint(SketchPlugin_ConstraintCoincidence::ID(),
940 theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()),
941 theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
942 theCreatedFeatures.insert(aConstraintFeature);
944 aConstraintFeature = createConstraintForObjects(SketchPlugin_ConstraintTangent::ID(),
945 getFeatureResult(theSplitFeature),
946 getFeatureResult(theBaseFeatureModified));
947 theCreatedFeatures.insert(aConstraintFeature);
950 void SketchPlugin_ConstraintSplit::arrangePointsOnLine(
951 const AttributePoint2DPtr& theStartPointAttr,
952 const AttributePoint2DPtr& theEndPointAttr,
953 AttributePoint2DPtr& theFirstPointAttr,
954 AttributePoint2DPtr& theLastPointAttr) const
956 // if first point is closer to last point, swap first and last values
957 if (theStartPointAttr->pnt()->distance(theFirstPointAttr->pnt()) >
958 theStartPointAttr->pnt()->distance(theLastPointAttr->pnt())) {
959 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
960 theFirstPointAttr = theLastPointAttr;
961 theLastPointAttr = aTmpPoint;
965 void SketchPlugin_ConstraintSplit::arrangePointsOnArc(
966 const FeaturePtr& theArc,
967 const std::shared_ptr<GeomDataAPI_Point2D>& theStartPointAttr,
968 const std::shared_ptr<GeomDataAPI_Point2D>& theEndPointAttr,
969 std::shared_ptr<GeomDataAPI_Point2D>& theFirstPointAttr,
970 std::shared_ptr<GeomDataAPI_Point2D>& theSecondPointAttr) const
972 static const double anAngleTol = 1.e-12;
974 std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
975 theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
976 bool isReversed = theArc->boolean(SketchPlugin_Arc::INVERSED_ID())->value();
978 // collect directions to each point
979 std::shared_ptr<GeomAPI_Dir2d> aStartDir(
980 new GeomAPI_Dir2d(theStartPointAttr->pnt()->xy()->decreased(aCenter->xy())));
981 std::shared_ptr<GeomAPI_Dir2d> aFirstPtDir(
982 new GeomAPI_Dir2d(theFirstPointAttr->pnt()->xy()->decreased(aCenter->xy())));
983 std::shared_ptr<GeomAPI_Dir2d> aSecondPtDir(
984 new GeomAPI_Dir2d(theSecondPointAttr->pnt()->xy()->decreased(aCenter->xy())));
986 // sort points by their angular values
987 double aFirstPtAngle = aStartDir->angle(aFirstPtDir);
988 double aSecondPtAngle = aStartDir->angle(aSecondPtDir);
989 double aPeriod = isReversed ? -2.0 * PI : 2.0 * PI;
990 if (fabs(aFirstPtAngle) > anAngleTol && isReversed == (aFirstPtAngle > 0.))
991 aFirstPtAngle += aPeriod;
992 if (fabs(aSecondPtAngle) > anAngleTol && isReversed == (aSecondPtAngle > 0.))
993 aSecondPtAngle += aPeriod;
995 if (fabs(aFirstPtAngle) > fabs(aSecondPtAngle)) {
996 AttributePoint2DPtr aTmpPoint = theFirstPointAttr;
997 theFirstPointAttr = theSecondPointAttr;
998 theSecondPointAttr = aTmpPoint;
1002 void SketchPlugin_ConstraintSplit::fillAttribute(const AttributePtr& theModifiedAttribute,
1003 const AttributePtr& theSourceAttribute)
1005 AttributePoint2DPtr aModifiedAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1006 theModifiedAttribute);
1007 AttributePoint2DPtr aSourceAttribute = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
1008 theSourceAttribute);
1010 if (aModifiedAttribute.get() && aSourceAttribute.get())
1011 aModifiedAttribute->setValue(aSourceAttribute->pnt());
1014 FeaturePtr SketchPlugin_ConstraintSplit::createLineFeature(const FeaturePtr& theBaseFeature,
1015 const AttributePtr& theFirstPointAttr,
1016 const AttributePtr& theSecondPointAttr)
1018 FeaturePtr aFeature;
1019 SketchPlugin_Sketch* aSketch = sketch();
1020 if (!aSketch || !theBaseFeature.get())
1023 aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
1025 fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPointAttr);
1026 fillAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPointAttr);
1027 aFeature->execute(); // to obtain result
1032 FeaturePtr SketchPlugin_ConstraintSplit::createArcFeature(const FeaturePtr& theBaseFeature,
1033 const AttributePtr& theFirstPointAttr,
1034 const AttributePtr& theSecondPointAttr)
1036 FeaturePtr aFeature;
1037 SketchPlugin_Sketch* aSketch = sketch();
1038 if (!aSketch || !theBaseFeature.get())
1041 std::string aCenterAttributeId;
1042 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
1043 aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
1044 else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
1045 aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
1047 if (aCenterAttributeId.empty())
1050 aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
1051 // update fillet arc: make the arc correct for sure, so, it is not needed to process the "attribute updated"
1052 // by arc; moreover, it may cause cyclicity in hte mechanism of updater
1053 aFeature->data()->blockSendAttributeUpdated(true);
1055 aFeature->string(SketchPlugin_Arc::ARC_TYPE())->setValue(
1056 SketchPlugin_Arc::ARC_TYPE_CENTER_START_END());
1058 fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
1059 theBaseFeature->attribute(aCenterAttributeId));
1060 fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
1061 fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
1063 /// fill referersed state of created arc as it is on the base arc
1064 if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
1065 bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->value();
1066 aFeature->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(aReversed);
1068 aFeature->data()->blockSendAttributeUpdated(false);
1069 aFeature->execute(); // to obtain result
1074 FeaturePtr SketchPlugin_ConstraintSplit::createConstraint(const std::string& theConstraintId,
1075 const AttributePtr& theFirstAttribute,
1076 const AttributePtr& theSecondAttribute)
1078 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1079 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1080 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1081 aRefAttr->setAttr(theFirstAttribute);
1083 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1084 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1085 aRefAttr->setAttr(theSecondAttribute);
1090 FeaturePtr SketchPlugin_ConstraintSplit::createConstraintForObjects(const std::string& theConstraintId,
1091 const ObjectPtr& theFirstObject,
1092 const ObjectPtr& theSecondObject)
1094 FeaturePtr aConstraint = sketch()->addFeature(theConstraintId);
1095 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1096 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
1097 aRefAttr->setObject(theFirstObject);
1099 aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
1100 aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
1101 aRefAttr->setObject(theSecondObject);
1106 std::shared_ptr<ModelAPI_Result> SketchPlugin_ConstraintSplit::getFeatureResult(
1107 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1109 std::shared_ptr<ModelAPI_Result> aResult;
1111 std::string aFeatureKind = theFeature->getKind();
1112 if (aFeatureKind == SketchPlugin_Line::ID())
1113 aResult = theFeature->firstResult();
1114 else if (aFeatureKind == SketchPlugin_Arc::ID())
1115 aResult = theFeature->lastResult();
1116 else if (aFeatureKind == SketchPlugin_Circle::ID())
1117 aResult = theFeature->lastResult();
1122 std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_ConstraintSplit::getEdgeAttributes(
1123 const std::shared_ptr<ModelAPI_Feature>& theFeature)
1125 std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes;
1127 std::string aFeatureKind = theFeature->getKind();
1128 if (aFeatureKind == SketchPlugin_Line::ID()) {
1129 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::START_ID()));
1130 anAttributes.insert(theFeature->attribute(SketchPlugin_Line::END_ID()));
1132 else if (aFeatureKind == SketchPlugin_Arc::ID()) {
1133 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::START_ID()));
1134 anAttributes.insert(theFeature->attribute(SketchPlugin_Arc::END_ID()));
1136 else if (aFeatureKind == SketchPlugin_Circle::ID()) {
1139 return anAttributes;
1143 std::string SketchPlugin_ConstraintSplit::getFeatureInfo(
1144 const std::shared_ptr<ModelAPI_Feature>& theFeature,
1145 const bool isUseAttributesInfo)
1148 if (!theFeature.get()) {
1152 if (theFeature->data()->isValid())
1153 anInfo.append(theFeature->data()->name().c_str());
1155 if (isUseAttributesInfo) {
1156 std::string aPointsInfo = ModelGeomAlgo_Point2D::getPontAttributesInfo(theFeature,
1157 getEdgeAttributes(theFeature));
1158 if (!aPointsInfo.empty()) { /// processing of feature with point 2d attributes, like line, arc, circle
1161 anInfo += aPointsInfo;
1163 else { /// process constraint coincidence, find points in ref attr attributes
1164 std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
1165 ModelAPI_AttributeRefAttr::typeId());
1166 std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
1167 std::string anAttributesInfo;
1168 for(; anIt != aLast; anIt++) {
1169 if (!anAttributesInfo.empty()) {
1170 anAttributesInfo.append(", ");
1171 anAttributesInfo += "\n";
1173 AttributePtr anAttr = *anIt;
1174 std::string aValue = "not defined";
1175 std::string aType = anAttr->attributeType();
1176 if (aType == ModelAPI_AttributeRefAttr::typeId()) {
1177 std::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
1178 std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
1179 if (aRefAttr.get()) {
1180 if (aRefAttr->isObject()) {
1181 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
1182 aValue = "<object:>" + getFeatureInfo(aFeature, false);
1185 AttributePtr anAttribute = aRefAttr->attr();
1186 if (anAttribute.get()) {
1187 FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
1188 aValue = "<attr:>" + ModelGeomAlgo_Point2D::getPointAttributeInfo(anAttribute) +
1189 " [" + getFeatureInfo(aFeature, false) + "]";
1194 anAttributesInfo.append(" " + anAttr->id() + ": " + aValue);
1196 if (!anAttributesInfo.empty())
1197 anInfo = anInfo + "\n" + anAttributesInfo;