Split and Trim features for ellipse and elliptic arc.
theCenter->xy()->multiplied(2.0)->decreased(theFocus->xy())));
theMajorRadius = 0.5 * (thePassed->distance(theFocus) + thePassed->distance(aSecondFocus));
- GeomDir2dPtr aXAxis(new GeomAPI_Dir2d(theFocus->x() - theCenter->x(),
- theFocus->y() - theCenter->y()));
- std::shared_ptr<GeomAPI_XY> aPassedVec = thePassed->xy()->decreased(theCenter->xy());
-
- double x = aPassedVec->dot(aXAxis->xy()) / theMajorRadius;
- double y = abs(aPassedVec->cross(aXAxis->xy()));
- theMinorRadius = y / sqrt(1.0 - x * x);
+ double aFocalDist = theCenter->distance(theFocus);
+ theMinorRadius = sqrt(theMajorRadius * theMajorRadius - aFocalDist * aFocalDist);
}
bool SketchPlugin_EllipticArc::fillCharacteristicPoints()
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(FIRST_FOCUS_ID()));
std::shared_ptr<GeomDataAPI_Point2D> aStartPointAttr =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(START_POINT_ID()));
+ std::shared_ptr<GeomDataAPI_Point2D> aEndPointAttr =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_POINT_ID()));
if (!aCenterAttr->isInitialized() ||
!aFocusAttr->isInitialized() ||
double aMajorRadius = 0.0, aMinorRadius = 0.0;
calculateRadii(aCenter2d, aFocus2d, aStart2d, aMajorRadius, aMinorRadius);
- if (aMinorRadius < tolerance)
+ if (aMinorRadius < tolerance *aMajorRadius)
return false;
real(MAJOR_RADIUS_ID())->setValue(aMajorRadius);
real(MINOR_RADIUS_ID())->setValue(aMinorRadius);
->setValue(aCenter2d->x() + aMinorDir2d->x() * aMinorRadius,
aCenter2d->y() + aMinorDir2d->y() * aMinorRadius);
- std::shared_ptr<GeomDataAPI_Point2D> aEndPointAttr =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(END_POINT_ID()));
if (aEndPointAttr->isInitialized()) {
// recalculate REVERSED flag
std::shared_ptr<GeomAPI_Ellipse2d> anEllipseForArc(
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMiddle.h>
//std::map<FeaturePtr, IdToPointPair> aTangentFeatures;
std::map<FeaturePtr, IdToPointPair> aCoincidenceToFeature;
- getConstraints(aFeaturesToDelete, aFeaturesToUpdate, /*aTangentFeatures, */
- aCoincidenceToFeature);
+ getConstraints(aFeaturesToDelete, aFeaturesToUpdate, aCoincidenceToFeature);
std::map<AttributePtr, std::list<AttributePtr> > aBaseRefAttributes;
std::list<AttributePtr> aRefsToFeature;
else if (aFeatureKind == SketchPlugin_Arc::ID())
aNewFeature = splitArc(aSplitFeature, aBaseFeature, anAfterFeature, aFurtherCoincidences,
aCreatedFeatures, aModifiedAttributes);
+ else if (aFeatureKind == SketchPlugin_EllipticArc::ID())
+ aNewFeature = splitEllipticArc(aSplitFeature, aBaseFeature, anAfterFeature,
+ aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
restoreCurrentFeature();
- if (aFeatureKind == SketchPlugin_Circle::ID()) {
- FeaturePtr aCircleFeature = aBaseFeature;
- aReplacingFeature = splitCircle(aSplitFeature, aBaseFeature, anAfterFeature,
+ if (aFeatureKind == SketchPlugin_Circle::ID() || aFeatureKind == SketchPlugin_Ellipse::ID()) {
+ aFeaturesToDelete.insert(aBaseFeature);
+ aReplacingFeature = splitClosed(aSplitFeature, aBaseFeature, anAfterFeature,
aFurtherCoincidences, aCreatedFeatures, aModifiedAttributes);
updateRefFeatureConstraints(aBaseFeature->lastResult(), aRefsToFeature);
- AttributePtr aCenterAttr = aCircleFeature->attribute(SketchPlugin_Circle::CENTER_ID());
- aFeaturesToDelete.insert(aCircleFeature);
// as circle is removed, temporary fill this attribute*/
aBaseObjectAttr->setObject(ResultPtr());
}
theFeaturesToDelete.insert(aRefFeature);
else if (aRefFeatureKind == SketchPlugin_ConstraintLength::ID())
theFeaturesToUpdate.insert(aRefFeature);
- else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID()) {
+ else if (aRefFeatureKind == SketchPlugin_ConstraintCoincidence::ID() ||
+ aRefFeatureKind == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
std::string anAttributeToBeModified;
AttributePoint2DPtr aCoincidentPoint;
AttributeRefAttrPtr anAttrA = aRefFeature->refattr(SketchPlugin_Constraint::ENTITY_A());
aNewCoincidencesToSplitFeature.insert(anEndPointAttr);
std::map<FeaturePtr, IdToPointPair>::const_iterator aCIt = theCoincidenceToFeature.begin(),
- aCLast = theCoincidenceToFeature.end();
+ aCLast = theCoincidenceToFeature.end();
#ifdef DEBUG_SPLIT
std::cout << std::endl;
std::cout << "Coincidences to feature(modified):"<< std::endl;
}
FeaturePtr SketchPlugin_Split::splitLine(FeaturePtr& theSplitFeature,
- FeaturePtr& theBaseFeatureModified,
- FeaturePtr& theAfterFeature,
- std::set<AttributePoint2DPtr>& thePoints,
- std::set<FeaturePtr>& theCreatedFeatures,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
{
FeaturePtr anNewFeature;
FeaturePtr aConstraintFeature;
theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch)
- return anNewFeature;
-
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
data()->attribute(SELECTED_OBJECT()));
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- std::string aFeatureKind = aBaseFeature->getKind();
- if (aFeatureKind != SketchPlugin_Line::ID())
- return anNewFeature;
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
#endif
// create a split feature
- theSplitFeature =
- createLineFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ theSplitFeature = SketchPlugin_SegmentationTools::createLineFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
theCreatedFeatures.insert(theSplitFeature);
// before split feature
aFeature->execute(); // to update result
}
else {
- aFeature = createLineFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
+ aFeature = SketchPlugin_SegmentationTools::createLineFeature(
+ aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
theCreatedFeatures.insert(aFeature);
theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
aFeature->attribute(SketchPlugin_Line::END_ID())));
}
FeaturePtr SketchPlugin_Split::splitArc(FeaturePtr& theSplitFeature,
- FeaturePtr& theBaseFeatureModified,
- FeaturePtr& theAfterFeature,
- std::set<AttributePoint2DPtr>& thePoints,
- std::set<FeaturePtr>& theCreatedFeatures,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
{
FeaturePtr anNewFeature;
FeaturePtr aConstraintFeature;
theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch)
- return anNewFeature;
-
- AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SELECTED_OBJECT()));
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- std::string aFeatureKind = aBaseFeature->getKind();
- if (aFeatureKind != SketchPlugin_Arc::ID())
- return anNewFeature;
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
#endif
// split feature
- theSplitFeature = createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
theCreatedFeatures.insert(theSplitFeature);
// before split feature
aFeature->execute(); // to update result
}
else {
- aFeature = createArcFeature(aBaseFeature, aSecondPointAttrOfSplit, anEndPointAttrOfBase);
+ aFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
theCreatedFeatures.insert(aFeature);
theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
aFeature->attribute(SketchPlugin_Arc::END_ID())));
return anNewFeature;
}
-FeaturePtr SketchPlugin_Split::splitCircle(FeaturePtr& theSplitFeature,
+FeaturePtr SketchPlugin_Split::splitEllipticArc(FeaturePtr& theSplitFeature,
+ FeaturePtr& theBaseFeatureModified,
+ FeaturePtr& theAfterFeature,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<FeaturePtr>& theCreatedFeatures,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
+{
+ FeaturePtr anNewFeature;
+
+ std::set<FeaturePtr> aCreatedFeatures;
+ FeaturePtr aConstraintFeature;
+ theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
+
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
+ FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
+
+ AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
+ AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
+ AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ if (!aStartPointAttrOfBase.get() && !anEndPointAttrOfBase.get()) {
+ setError("Error: Feature has no start and end points.");
+ return anNewFeature;
+ }
+
+ arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
+ aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+#ifdef DEBUG_SPLIT
+ std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
+ std::cout << "Start point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aStartPointAttrOfBase) << std::endl;
+ std::cout << "1st point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aFirstPointAttrOfSplit) << std::endl;
+ std::cout << "2nd point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(aSecondPointAttrOfSplit) << std::endl;
+ std::cout << "End point: " <<
+ ModelGeomAlgo_Point2D::getPointAttributeInfo(anEndPointAttrOfBase) << std::endl;
+#endif
+
+ // split feature
+ theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
+ theCreatedFeatures.insert(theSplitFeature);
+
+ // before split feature
+ if (aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
+ theModifiedAttributes.insert(std::make_pair(aStartPointAttrOfBase,
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+ }
+ else {
+ theBaseFeatureModified = aBaseFeature; // use base feature to store all constraints here
+ // move end arc point to start of split
+ }
+
+ // after split feature
+ if (!aSecondPointAttrOfSplit->pnt()->isEqual(anEndPointAttrOfBase->pnt())) {
+ FeaturePtr aFeature;
+ if (!theBaseFeatureModified.get()) {
+ aFeature = aBaseFeature; // use base feature to store all constraints here
+ fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), aSecondPointAttrOfSplit);
+ aFeature->execute(); // to update result
+ }
+ else {
+ aFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aSecondPointAttrOfSplit->pnt(), anEndPointAttrOfBase->pnt());
+ theCreatedFeatures.insert(aFeature);
+ theModifiedAttributes.insert(std::make_pair(
+ anEndPointAttrOfBase, aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ anNewFeature = aFeature;
+ }
+ aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
+ SketchPlugin_ConstraintCoincidence::ID(),
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ theCreatedFeatures.insert(aConstraintFeature);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+
+ if (!theBaseFeatureModified.get())
+ theBaseFeatureModified = aFeature;
+ else
+ theAfterFeature = aFeature;
+ }
+ else {
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ theModifiedAttributes.insert(std::make_pair(anEndPointAttrOfBase,
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ }
+ // base split, that is defined before split feature should be changed at end
+ // (after the after feature creation). Otherwise modified value will be used in after feature
+ // before split feature
+ if (!aStartPointAttrOfBase->pnt()->isEqual(aFirstPointAttrOfSplit->pnt())) {
+ // move end arc point to start of split
+ fillAttribute(theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ aFirstPointAttrOfSplit);
+ theBaseFeatureModified->execute(); // to update result
+ aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
+ SketchPlugin_ConstraintCoincidence::ID(),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID()),
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ theCreatedFeatures.insert(aConstraintFeature);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+ }
+ else
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theSplitFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+
+ // additional constraints between split and base features
+#ifdef CREATE_CONSTRAINTS
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintEqual::ID(),
+ aBaseFeature->lastResult(),
+ theSplitFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintTangent::ID(),
+ theSplitFeature->lastResult(),
+ aBaseFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ if (theAfterFeature.get()) {
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintEqual::ID(),
+ aBaseFeature->lastResult(),
+ theAfterFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ aConstraintFeature = SketchPlugin_Tools::createConstraint(sketch(),
+ SketchPlugin_ConstraintTangent::ID(),
+ theSplitFeature->lastResult(),
+ theAfterFeature->lastResult());
+ theCreatedFeatures.insert(aConstraintFeature);
+ }
+#endif
+ return anNewFeature;
+}
+
+FeaturePtr SketchPlugin_Split::splitClosed(FeaturePtr& theSplitFeature,
FeaturePtr& theBaseFeatureModified,
FeaturePtr& theAfterFeature,
std::set<AttributePoint2DPtr>& thePoints,
FeaturePtr aConstraintFeature;
theBaseFeatureModified = FeaturePtr(); // it will contain modified base feature
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch)
- return anNewFeature;
-
- AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SELECTED_OBJECT()));
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- std::string aFeatureKind = aBaseFeature->getKind();
- if (aFeatureKind != SketchPlugin_Circle::ID())
- return anNewFeature;
AttributePoint2DPtr aFirstPointAttrOfSplit = getPointAttribute(true);
AttributePoint2DPtr aSecondPointAttrOfSplit = getPointAttribute(false);
// split feature
- theSplitFeature =
- createArcFeature(aBaseFeature, aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
- bool aSplitReversed = std::dynamic_pointer_cast<SketchPlugin_Arc>(theSplitFeature)->isReversed();
+ theSplitFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
+ const std::string& aReversedAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+ bool aSplitReversed = theSplitFeature->boolean(aReversedAttrName)->value();
theCreatedFeatures.insert(theSplitFeature);
// base feature is a left part of the circle
- theBaseFeatureModified = createArcFeature(aBaseFeature,
- aFirstPointAttrOfSplit, aSecondPointAttrOfSplit);
+ theBaseFeatureModified = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aFirstPointAttrOfSplit->pnt(), aSecondPointAttrOfSplit->pnt());
anNewFeature = theBaseFeatureModified;
- std::dynamic_pointer_cast<SketchPlugin_Arc>(
- theBaseFeatureModified)->setReversed(!aSplitReversed);
+ theBaseFeatureModified->boolean(aReversedAttrName)->setValue(!aSplitReversed);
theBaseFeatureModified->execute();
- theModifiedAttributes.insert(
- std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
- theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
+ if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_Arc::CENTER_ID())));
+ }
+ else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
+ theBaseFeatureModified->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
+
+ // update the PARENT_ID reference for all the features created by the ellipse
+ const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
+ std::list<AttributePtr> aRefsToParent;
+ for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
+ if ((*aRef)->id() == SketchPlugin_Line::PARENT_ID() ||
+ (*aRef)->id() == SketchPlugin_Point::PARENT_ID())
+ aRefsToParent.push_back(*aRef);
+ }
+ for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
+ aRef != aRefsToParent.end(); ++aRef)
+ std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(theSplitFeature);
+ }
theCreatedFeatures.insert(theBaseFeatureModified);
+ const std::string& aStartAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
+ const std::string& aEndAttrName = theSplitFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
+
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID())));
+ (theBaseFeatureModified->attribute(aStartAttrName)));
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID())));
+ (theBaseFeatureModified->attribute(aEndAttrName)));
// additional constraints between split and base features
aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
SketchPlugin_ConstraintCoincidence::ID(),
- theBaseFeatureModified->attribute(SketchPlugin_Arc::END_ID()),
- theSplitFeature->attribute(SketchPlugin_Arc::END_ID()));
+ theBaseFeatureModified->attribute(aEndAttrName),
+ theSplitFeature->attribute(aEndAttrName));
theCreatedFeatures.insert(aConstraintFeature);
aConstraintFeature = SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
SketchPlugin_ConstraintCoincidence::ID(),
- theBaseFeatureModified->attribute(SketchPlugin_Arc::START_ID()),
- theSplitFeature->attribute(SketchPlugin_Arc::START_ID()));
+ theBaseFeatureModified->attribute(aStartAttrName),
+ theSplitFeature->attribute(aStartAttrName));
theCreatedFeatures.insert(aConstraintFeature);
#ifdef CREATE_CONSTRAINTS
{
static const double anAngleTol = 1.e-12;
+ const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
+ const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+
std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
- bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+ theArc->attribute(aCenterAttrName))->pnt();
+ bool isReversed = theArc->boolean(aReversedAttrName)->value();
// collect directions to each point
std::shared_ptr<GeomAPI_Dir2d> aStartDir(
}
}
-FeaturePtr SketchPlugin_Split::createLineFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr)
-{
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
-
- fillAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPointAttr);
- fillAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPointAttr);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- aFeature->execute(); // to obtain result
-
- return aFeature;
-}
-
-FeaturePtr SketchPlugin_Split::createArcFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr)
-{
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- std::string aCenterAttributeId;
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
- aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
- else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
- aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
-
- if (aCenterAttributeId.empty())
- return aFeature;
-
- aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
- // update fillet arc: make the arc correct for sure, so, it is not needed to process
- // the "attribute updated"
- // by arc; moreover, it may cause cyclicity in hte mechanism of updater
- bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
-
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
- theBaseFeature->attribute(aCenterAttributeId));
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPointAttr);
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPointAttr);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- // fill referersed state of created arc as it is on the base arc
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
- bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
- aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
- }
- aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
- aFeature->execute(); // to obtain result
-
- return aFeature;
-}
-
#ifdef _DEBUG
std::set<std::shared_ptr<ModelAPI_Attribute> > SketchPlugin_Split::getEdgeAttributes(
const std::shared_ptr<ModelAPI_Feature>& theFeature)
std::set<std::shared_ptr<ModelAPI_Feature>>& theCreatedFeatures,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+ /// Make the base object is splitted by the point attributes
+ /// \param theSplitFeature a result split feature
+ /// \param theBeforeFeature a feature between start point and the 1st point of split feature
+ /// \param theAfterFeature a feature between last point of split feature and the end point
+ /// \param thePoints a list of points where coincidences will be build
+ /// \param theCreatedFeatures a container of created features
+ /// \return new elliptic arc if it was created
+ FeaturePtr splitEllipticArc(std::shared_ptr<ModelAPI_Feature>& theSplitFeature,
+ std::shared_ptr<ModelAPI_Feature>& theBeforeFeature,
+ std::shared_ptr<ModelAPI_Feature>& theAfterFeature,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
+ std::set<std::shared_ptr<ModelAPI_Feature>>& theCreatedFeatures,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+
/// Make the base object is splitted by the point attributes
/// \param theSplitFeature a result split feature
/// \param theBeforeFeature a feature between start point and the 1st point of split feature
/// \param thePoints a list of points where coincidences will be build
/// \param theCreatedFeatures a container of created features
/// \return new arc if it was created
- FeaturePtr splitCircle(std::shared_ptr<ModelAPI_Feature>& theSplitFeature,
+ FeaturePtr splitClosed(std::shared_ptr<ModelAPI_Feature>& theSplitFeature,
std::shared_ptr<ModelAPI_Feature>& theBeforeFeature,
std::shared_ptr<ModelAPI_Feature>& theAfterFeature,
std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
void fillAttribute(const AttributePtr& theModifiedAttribute,
const AttributePtr& theSourceAttribute);
- /// Creates a line feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createLineFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr);
-
- /// Creates an arc feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature,
- const AttributePtr& theFirstPointAttr,
- const AttributePtr& theSecondPointAttr);
-
/// Returns attributes of the feature, used in edge build, for arc it is end and start points
/// \param theFeature a feature
/// \return container of attributes
#include "SketchPlugin_Tools.h"
#include "SketchPlugin_Arc.h"
+#include "SketchPlugin_Circle.h"
#include "SketchPlugin_ConstraintCoincidence.h"
#include "SketchPlugin_ConstraintCoincidenceInternal.h"
#include "SketchPlugin_ConstraintLength.h"
anAIS = AISObjectPtr();
return anAIS;
}
+
+#define GEOM_DATA_POINT2D(f, a) std::dynamic_pointer_cast<GeomDataAPI_Point2D>((f)->attribute(a))
+
+FeaturePtr SketchPlugin_SegmentationTools::createLineFeature(
+ const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
+{
+ FeaturePtr aFeature;
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
+ SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
+ if (!aSketch || !theBaseFeature.get())
+ return aFeature;
+
+ aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
+
+ GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::START_ID())->setValue(theFirstPoint);
+ GEOM_DATA_POINT2D(aFeature, SketchPlugin_Line::END_ID())->setValue(theSecondPoint);
+
+ aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
+ theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
+ aFeature->execute(); // to obtain result
+
+ return aFeature;
+}
+
+struct ArcAttributes
+{
+ std::string myKind;
+ std::string myCenter;
+ std::string myFocus;
+ std::string myStart;
+ std::string myEnd;
+ std::string myReversed;
+
+ ArcAttributes() {}
+
+ ArcAttributes(const std::string& theKind) : myKind(theKind)
+ {
+ if (myKind == SketchPlugin_Arc::ID()) {
+ myCenter = SketchPlugin_Arc::CENTER_ID();
+ myStart = SketchPlugin_Arc::START_ID();
+ myEnd = SketchPlugin_Arc::END_ID();
+ myReversed = SketchPlugin_Arc::REVERSED_ID();
+ }
+ else if (myKind == SketchPlugin_Circle::ID()) {
+ myCenter = SketchPlugin_Circle::CENTER_ID();
+ }
+ else if (myKind == SketchPlugin_Ellipse::ID()) {
+ myCenter = SketchPlugin_Ellipse::CENTER_ID();
+ myFocus = SketchPlugin_Ellipse::FIRST_FOCUS_ID();
+ }
+ else if (myKind == SketchPlugin_EllipticArc::ID()) {
+ myCenter = SketchPlugin_EllipticArc::CENTER_ID();
+ myFocus = SketchPlugin_EllipticArc::FIRST_FOCUS_ID();
+ myStart = SketchPlugin_EllipticArc::START_POINT_ID();
+ myEnd = SketchPlugin_EllipticArc::END_POINT_ID();
+ myReversed = SketchPlugin_EllipticArc::REVERSED_ID();
+ }
+ }
+};
+
+FeaturePtr SketchPlugin_SegmentationTools::createArcFeature(
+ const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
+{
+ FeaturePtr aFeature;
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theBaseFeature);
+ SketchPlugin_Sketch* aSketch = aSketchFeature->sketch();
+ if (!aSketch || !theBaseFeature.get())
+ return aFeature;
+
+ ArcAttributes aBaseAttrs(theBaseFeature->getKind());
+ ArcAttributes aTargetAttrs;
+ if (aBaseAttrs.myKind == SketchPlugin_Arc::ID() ||
+ aBaseAttrs.myKind == SketchPlugin_Circle::ID())
+ aTargetAttrs = ArcAttributes(SketchPlugin_Arc::ID());
+ else if (aBaseAttrs.myKind == SketchPlugin_Ellipse::ID() ||
+ aBaseAttrs.myKind == SketchPlugin_EllipticArc::ID())
+ aTargetAttrs = ArcAttributes(SketchPlugin_EllipticArc::ID());
+
+ if (aTargetAttrs.myKind.empty())
+ return aFeature;
+
+ aFeature = aSketch->addFeature(aTargetAttrs.myKind);
+ // update fillet arc: make the arc correct for sure, so, it is not needed to process
+ // the "attribute updated"
+ // by arc; moreover, it may cause cyclicity in hte mechanism of updater
+ bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
+
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myCenter)->setValue(
+ GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myCenter)->pnt());
+ if (!aTargetAttrs.myFocus.empty()) {
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myFocus)->setValue(
+ GEOM_DATA_POINT2D(theBaseFeature, aBaseAttrs.myFocus)->pnt());
+ }
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myStart)->setValue(theFirstPoint);
+ GEOM_DATA_POINT2D(aFeature, aTargetAttrs.myEnd)->setValue(theSecondPoint);
+
+ aFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->setValue(
+ theBaseFeature->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value());
+
+ /// fill referersed state of created arc as it is on the base arc
+ bool aReversed = aBaseAttrs.myReversed.empty() ? false :
+ theBaseFeature->boolean(aBaseAttrs.myReversed)->value();
+ aFeature->boolean(aTargetAttrs.myReversed)->setValue(aReversed);
+
+ aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
+ aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
+
+ return aFeature;
+}
/// \param theFeaturesToUpdate a constraint index
void updateFeaturesAfterOperation(const std::set<FeaturePtr>& theFeaturesToUpdate);
+
+ /// Creates a line feature filled by center of base feature and given points
+ /// \param theBaseFeature another arc feature
+ /// \param theFirstAttribute an attribute with coordinates for the start point
+ /// \param theSecondAttribute an attribute with coordinates for the end point
+ FeaturePtr createLineFeature(const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
+
+ /// Creates a circular/elliptic arc feature filled by center
+ /// (or by center and focus for elliptic arc) of base feature and given points
+ /// \param theBaseFeature another circle or ellipse or circular/elliptic arc
+ /// \param theFirstAttribute an attribute with coordinates for the start point
+ /// \param theSecondAttribute an attribute with coordinates for the end point
+ FeaturePtr createArcFeature(
+ const FeaturePtr& theBaseFeature,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
+
}; // namespace SketchPlugin_SegmentationTools
#endif // SKETCHPLUGIN_TOOLS_H_
\ No newline at end of file
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintCollinear.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
#include <cmath>
+#define DEBUG_TRIM
#ifdef DEBUG_TRIM
#include <iostream>
#endif
std::set<std::pair<AttributePtr, AttributePtr>> aModifiedAttributes;
const std::string& aKind = aBaseFeature->getKind();
FeaturePtr aReplacingFeature, aNewFeature;
- if (aKind == SketchPlugin_Circle::ID()) {
- aReplacingFeature = trimCircle(aStartShapePoint2d, aLastShapePoint2d,
+ if (aKind == SketchPlugin_Circle::ID() ||
+ aKind == SketchPlugin_Ellipse::ID()) {
+ aReplacingFeature = trimClosed(aStartShapePoint2d, aLastShapePoint2d,
aFurtherCoincidences, aModifiedAttributes);
aFeaturesToDelete.insert(aBaseFeature);
aNewFeature = trimArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
aFurtherCoincidences, aModifiedAttributes);
}
+ else if (aKind == SketchPlugin_EllipticArc::ID()) {
+ aNewFeature = trimEllipticArc(aStartShapePoint2d, aLastShapePoint2d, aBaseRefAttributes,
+ aFurtherCoincidences, aModifiedAttributes);
+ }
restoreCurrentFeature();
ResultPtr aReplacingResult;
if (aReplacingFeature.get()) {
aReplacingFeature->execute(); // need it to obtain result
- aReplacingResult = getFeatureResult(aReplacingFeature);
+ aReplacingResult = aReplacingFeature->lastResult();
}
for(std::list<AttributePtr>::const_iterator anIt = aRefsToFeature.begin(),
aLast = aRefsToFeature.end();
aPreviewObject = ObjectPtr();
aBaseFeature->execute(); // should recompute shapes of result to do not check obsolete one
- aBaseObject = getFeatureResult(aBaseFeature);
+ aBaseObject = aBaseFeature->lastResult();
std::shared_ptr<GeomAPI_Pnt> aPreviewPnt = sketch()->to3D(aPreviewPnt2d->x(),
aPreviewPnt2d->y());
ResultPtr aBaseResult = std::dynamic_pointer_cast<ModelAPI_Result>(aBaseObject);
aPreviewObject = aBaseResult;
}
if (!aPreviewObject.get() && aNewFeature.get()) {
- ResultPtr aNewFeatureResult = getFeatureResult(aNewFeature);
+ ResultPtr aNewFeatureResult = aNewFeature->lastResult();
if (aNewFeatureResult.get()) {
GeomShapePtr aShape = aNewFeatureResult->shape();
std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
aData->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- ResultPtr aBaseFeatureResult = getFeatureResult(aBaseFeature);
+ ResultPtr aBaseFeatureResult = aBaseFeature->lastResult();
std::set<AttributePtr> aRefsList = aBaseFeatureResult->data()->refsToMe();
std::set<AttributePtr> aFRefsList = aBaseFeature->data()->refsToMe();
// result is two lines: start line point - start shape point,
// last shape point - last line point
// create second line
- anNewFeature = createLineFeature(aBaseFeature, aLastShapePoint, aLastFeaturePoint);
+ anNewFeature = SketchPlugin_SegmentationTools::createLineFeature(
+ aBaseFeature, aLastShapePoint, aLastFeaturePoint);
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
(anNewFeature->attribute(SketchPlugin_Line::START_ID())));
// Collinear constraint for lines
SketchPlugin_Tools::createConstraintObjectObject(sketch(),
SketchPlugin_ConstraintCollinear::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(anNewFeature));
+ aBaseFeature->lastResult(),
+ anNewFeature->lastResult());
}
return anNewFeature;
}
else {
// result is two arcs: start arc point - start shape point, last shape point - last arc point
// create second arc
- anNewFeature = createArcFeature(aBaseFeature, aLastShapePoint, aLastArcPoint);
+ anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aLastShapePoint, aLastArcPoint);
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
(anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
// equal Radius constraint for arcs
SketchPlugin_Tools::createConstraintObjectObject(sketch(),
SketchPlugin_ConstraintEqual::ID(),
- getFeatureResult(aBaseFeature),
- getFeatureResult(anNewFeature));
+ aBaseFeature->lastResult(),
+ anNewFeature->lastResult());
// coincident centers constraint
SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
SketchPlugin_ConstraintCoincidence::ID(),
return anNewFeature;
}
-FeaturePtr SketchPlugin_Trim::trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
- std::set<AttributePoint2DPtr>& thePoints,
+FeaturePtr SketchPlugin_Trim::trimEllipticArc(
+ const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ std::set<AttributePoint2DPtr>& thePoints,
std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
{
+ FeaturePtr anNewFeature;
// Check the base objects are initialized.
- AttributeReferencePtr aBaseObjectAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
- data()->attribute(SketchPlugin_Trim::SELECTED_OBJECT()));
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
ObjectPtr aBaseObject = aBaseObjectAttr->value();
FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
- /// points of trim
- //AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
- //getFeaturePoints(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+ // points of trim
+ AttributePoint2DPtr aStartPointAttrOfBase, anEndPointAttrOfBase;
+ SketchPlugin_SegmentationTools::getFeaturePoints(
+ aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase);
+
+ std::shared_ptr<GeomAPI_Pnt2d> aStartArcPoint = aStartPointAttrOfBase->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aLastArcPoint = anEndPointAttrOfBase->pnt();
+
+ std::shared_ptr<GeomAPI_Pnt2d> aStartShapePoint = theStartShapePoint;
+ std::shared_ptr<GeomAPI_Pnt2d> aLastShapePoint = theLastShapePoint;
+ arrangePointsOnArc(aBaseFeature, aStartPointAttrOfBase, anEndPointAttrOfBase,
+ aStartShapePoint, aLastShapePoint);
+#ifdef DEBUG_TRIM
+ std::cout << "Arranged points (to build split between 1st and 2nd points:" << std::endl;
+ if (aStartShapePoint.get())
+ std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
+ aStartShapePoint->y() << "]" << std::endl;
+ std::cout << "Start arc attribute point: [" << aStartArcPoint->x() << ", " <<
+ aStartArcPoint->y() << "]" << std::endl;
+ if (aLastShapePoint.get())
+ std::cout << "Last shape point: [" << aLastShapePoint->x() << ", " <<
+ aLastShapePoint->y() << "]" << std::endl;
+ std::cout << "Last arc attribute point: [" << aLastArcPoint->x() << ", " <<
+ aLastArcPoint->y() << "]" << std::endl;
+#endif
+
+ bool isStartPoint = !aStartShapePoint.get() || aStartArcPoint->isEqual(aStartShapePoint);
+ bool isLastPoint = !aLastShapePoint.get() || aLastArcPoint->isEqual(aLastShapePoint);
+ if (isStartPoint || isLastPoint) {
+ // result is one arc: changed existing arc
+ std::string aModifiedAttribute = isStartPoint ? SketchPlugin_EllipticArc::START_POINT_ID()
+ : SketchPlugin_EllipticArc::END_POINT_ID();
+ std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+ if (aStartShapePoint.get() && aLastShapePoint.get())
+ aPoint = isStartPoint ? aLastShapePoint : aStartShapePoint;
+ else
+ aPoint = aStartShapePoint.get() ? aStartShapePoint : aLastShapePoint;
+
+ removeReferencesToAttribute(aBaseFeature->attribute(aModifiedAttribute),
+ theBaseRefAttributes);
+
+ fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aPoint);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aBaseFeature->attribute(aModifiedAttribute)));
+ }
+ else {
+ // result is two arcs: start arc point - start shape point, last shape point - last arc point
+ // create second arc
+ anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, aLastShapePoint, aLastArcPoint);
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ anNewFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID())));
+
+ std::string aModifiedAttribute = SketchPlugin_EllipticArc::END_POINT_ID();
+ theModifiedAttributes.insert(
+ std::make_pair(aBaseFeature->attribute(aModifiedAttribute),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID())));
+
+ // modify base arc
+ fillPointAttribute(aBaseFeature->attribute(aModifiedAttribute), aStartShapePoint);
+
+ thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
+ (aBaseFeature->attribute(aModifiedAttribute)));
- /// trim feature
- FeaturePtr anNewFeature = createArcFeature(aBaseFeature, theStartShapePoint, theLastShapePoint);
+ // make elliptic arcs equal
+ SketchPlugin_Tools::createConstraintObjectObject(sketch(),
+ SketchPlugin_ConstraintEqual::ID(),
+ aBaseFeature->lastResult(),
+ anNewFeature->lastResult());
+ // coincident centers constraint
+ SketchPlugin_Tools::createConstraintAttrAttr(sketch(),
+ SketchPlugin_ConstraintCoincidence::ID(),
+ aBaseFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID()));
+
+#ifdef DEBUG_TRIM
+ std::cout << "Created arc on points:" << std::endl;
+ std::cout << "Start shape point: [" << aStartShapePoint->x() << ", " <<
+ aStartShapePoint->y() << "]" << std::endl;
+#endif
+ }
+ return anNewFeature;
+}
+
+FeaturePtr SketchPlugin_Trim::trimClosed(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::set<AttributePoint2DPtr>& thePoints,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes)
+{
+ // Check the base objects are initialized.
+ AttributeReferencePtr aBaseObjectAttr = reference(SELECTED_OBJECT());
+ ObjectPtr aBaseObject = aBaseObjectAttr->value();
+ FeaturePtr aBaseFeature = ModelAPI_Feature::feature(aBaseObjectAttr->value());
+
+ // trim feature
+ FeaturePtr anNewFeature = SketchPlugin_SegmentationTools::createArcFeature(
+ aBaseFeature, theStartShapePoint, theLastShapePoint);
// arc created by trim of circle is always correct, that means that it is not inversed
- anNewFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(false);
+ const std::string& aReversedAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+ anNewFeature->boolean(aReversedAttrName)->setValue(false);
+
+ if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
+ theModifiedAttributes.insert(
+ std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
+ anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
+ }
+ else if (aBaseFeature->getKind() == SketchPlugin_Ellipse::ID()) {
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::CENTER_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::FIRST_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::SECOND_FOCUS_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_START_ID())));
+ theModifiedAttributes.insert(std::make_pair(
+ aBaseFeature->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()),
+ anNewFeature->attribute(SketchPlugin_EllipticArc::MINOR_AXIS_END_ID())));
+
+ // update the PARENT_ID reference for all the features created by the ellipse
+ const std::set<AttributePtr>& aRefs = aBaseFeature->data()->refsToMe();
+ std::list<AttributePtr> aRefsToParent;
+ for (std::set<AttributePtr>::const_iterator aRef = aRefs.begin(); aRef != aRefs.end(); ++aRef) {
+ if ((*aRef)->id() == SketchPlugin_Line::PARENT_ID() ||
+ (*aRef)->id() == SketchPlugin_Point::PARENT_ID())
+ aRefsToParent.push_back(*aRef);
+ }
+ for (std::list<AttributePtr>::iterator aRef = aRefsToParent.begin();
+ aRef != aRefsToParent.end(); ++aRef)
+ std::dynamic_pointer_cast<ModelAPI_AttributeReference>(*aRef)->setValue(anNewFeature);
+ }
- theModifiedAttributes.insert(
- std::make_pair(aBaseFeature->attribute(SketchPlugin_Circle::CENTER_ID()),
- anNewFeature->attribute(SketchPlugin_Arc::CENTER_ID())));
+ const std::string& aStartAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::START_ID() : SketchPlugin_EllipticArc::START_POINT_ID();
+ const std::string& aEndAttrName = anNewFeature->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::END_ID() : SketchPlugin_EllipticArc::END_POINT_ID();
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (anNewFeature->attribute(SketchPlugin_Arc::START_ID())));
+ (anNewFeature->attribute(aStartAttrName)));
thePoints.insert(std::dynamic_pointer_cast<GeomDataAPI_Point2D>
- (anNewFeature->attribute(SketchPlugin_Arc::END_ID())));
+ (anNewFeature->attribute(aEndAttrName)));
return anNewFeature;
}
static const double anAngleTol = 1.e-12;
+ const std::string& aCenterAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::CENTER_ID() : SketchPlugin_EllipticArc::CENTER_ID();
+ const std::string& aReversedAttrName = theArc->getKind() == SketchPlugin_Arc::ID() ?
+ SketchPlugin_Arc::REVERSED_ID() : SketchPlugin_EllipticArc::REVERSED_ID();
+
std::shared_ptr<GeomAPI_Pnt2d> aCenter = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- theArc->attribute(SketchPlugin_Arc::CENTER_ID()))->pnt();
- bool isReversed = theArc->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
+ theArc->attribute(aCenterAttrName))->pnt();
+ bool isReversed = theArc->boolean(aReversedAttrName)->value();
// collect directions to each point
std::shared_ptr<GeomAPI_Dir2d> aStartDir(
}
}
-
void SketchPlugin_Trim::fillAttribute(const AttributePtr& theModifiedAttribute,
const AttributePtr& theSourceAttribute)
{
aModifiedAttribute->setValue(aSourceAttribute->value());
}
}
-
-FeaturePtr SketchPlugin_Trim::createLineFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
-{
-#ifdef DEBUG_TRIM
- std::cout << "---- createLineFeature ---" << std::endl;
-#endif
-
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- aFeature = aSketch->addFeature(SketchPlugin_Line::ID());
-
- fillPointAttribute(aFeature->attribute(SketchPlugin_Line::START_ID()), theFirstPoint);
- fillPointAttribute(aFeature->attribute(SketchPlugin_Line::END_ID()), theSecondPoint);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- aFeature->execute(); // to obtain result
-
-#ifdef DEBUG_TRIM
- std::cout << "---- createLineFeature:end ---" << std::endl;
-#endif
-
- return aFeature;
-}
-
-FeaturePtr SketchPlugin_Trim::createArcFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint)
-{
- FeaturePtr aFeature;
- SketchPlugin_Sketch* aSketch = sketch();
- if (!aSketch || !theBaseFeature.get())
- return aFeature;
-
- std::string aCenterAttributeId;
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID())
- aCenterAttributeId = SketchPlugin_Arc::CENTER_ID();
- else if (theBaseFeature->getKind() == SketchPlugin_Circle::ID())
- aCenterAttributeId = SketchPlugin_Circle::CENTER_ID();
-
- if (aCenterAttributeId.empty())
- return aFeature;
-
-#ifdef DEBUG_TRIM
- std::cout << "---- createArcFeature ---" << std::endl;
-#endif
-
- aFeature = aSketch->addFeature(SketchPlugin_Arc::ID());
- // update fillet arc: make the arc correct for sure, so, it is not needed to process
- // the "attribute updated"
- // by arc; moreover, it may cause cyclicity in hte mechanism of updater
- bool aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
-
- fillAttribute(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()),
- theBaseFeature->attribute(aCenterAttributeId));
- fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::START_ID()), theFirstPoint);
- fillPointAttribute(aFeature->attribute(SketchPlugin_Arc::END_ID()), theSecondPoint);
-
- fillAttribute(aFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()),
- theBaseFeature->attribute(SketchPlugin_SketchEntity::AUXILIARY_ID()));
-
- /// fill referersed state of created arc as it is on the base arc
- if (theBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
- bool aReversed = theBaseFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->value();
- aFeature->boolean(SketchPlugin_Arc::REVERSED_ID())->setValue(aReversed);
- }
- aFeature->execute(); // to obtain result (need to calculate arc parameters before sending Update)
- aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
-
- #ifdef DEBUG_TRIM
- std::cout << "---- createArcFeature:end ---" << std::endl;
- #endif
-
- return aFeature;
-}
-
-std::shared_ptr<ModelAPI_Result> SketchPlugin_Trim::getFeatureResult(
- const std::shared_ptr<ModelAPI_Feature>& theFeature)
-{
- std::shared_ptr<ModelAPI_Result> aResult;
-
- std::string aFeatureKind = theFeature->getKind();
- if (aFeatureKind == SketchPlugin_Line::ID())
- aResult = theFeature->firstResult();
- else if (aFeatureKind == SketchPlugin_Arc::ID())
- aResult = theFeature->lastResult();
- else if (aFeatureKind == SketchPlugin_Circle::ID())
- aResult = theFeature->lastResult();
-
- return aResult;
-}
/// Make the base object is splitted by the point attributes
/// \param thePoints a list of points where coincidences will be build
- FeaturePtr trimCircle(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
- std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
- std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+ /// \return new elliptic arc if it was created
+ FeaturePtr trimEllipticArc(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::map<AttributePtr, std::list<AttributePtr> >& theBaseRefAttributes,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
+
+ /// Make the base object is splitted by the point attributes
+ /// \param thePoints a list of points where coincidences will be build
+ FeaturePtr trimClosed(const std::shared_ptr<GeomAPI_Pnt2d>& theStartShapePoint,
+ const std::shared_ptr<GeomAPI_Pnt2d>& theLastShapePoint,
+ std::set<std::shared_ptr<GeomDataAPI_Point2D> >& thePoints,
+ std::set<std::pair<AttributePtr, AttributePtr>>& theModifiedAttributes);
/// Correct the first and the second point to provide condition that the first is closer to
/// the start point and the second point - to the last end of current segment. To rearrange
void fillPointAttribute(const AttributePtr& theModifiedAttribute,
const std::shared_ptr<GeomAPI_Pnt2d>& thePoint);
- /// Creates a line feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createLineFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
-
- /// Creates an arc feature filled by center of base feature and given points
- /// \param theBaseFeature another arc feature
- /// \param theFirstAttribute an attribute with coordinates for the start point
- /// \param theSecondAttribute an attribute with coordinates for the end point
- FeaturePtr createArcFeature(const FeaturePtr& theBaseFeature,
- const std::shared_ptr<GeomAPI_Pnt2d>& theFirstPoint,
- const std::shared_ptr<GeomAPI_Pnt2d>& theSecondPoint);
-
- /// Result result of the feature to build constraint with. For arc, circle it is an edge result.
- /// \param theFeature a feature
- /// \return result object
- std::shared_ptr<ModelAPI_Result> getFeatureResult(
- const std::shared_ptr<ModelAPI_Feature>& theFeature);
-
private:
void findShapePoints(const std::string& theObjectAttributeId,
const std::string& thePointAttributeId,
GeomShapePtr anAttrShape = (*anEdgeShapes.begin())->shape();
std::shared_ptr<SketchPlugin_Feature> aSFeature =
std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttrFeature);
+ if (!aSFeature)
+ return false;
SketchPlugin_Sketch* aSketch = aSFeature->sketch();
std::shared_ptr<ModelAPI_Data> aData = aSketch->data();
createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity);
+static ConstraintWrapperPtr
+ createConstraintPointsCollinear(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint3);
static ConstraintWrapperPtr
createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
+ std::shared_ptr<PlaneGCSSolver_EdgeWrapper> anEntity1 = GCS_EDGE_WRAPPER(theEntity1);
switch (theType) {
case CONSTRAINT_PT_PT_COINCIDENT:
aResult = createConstraintCoincidence(aPoint1, aPoint2);
break;
case CONSTRAINT_PT_ON_CURVE:
- aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_EDGE_WRAPPER(theEntity1));
+ aResult = anEntity1 ? createConstraintPointOnEntity(theType, aPoint1, anEntity1):
+ createConstraintPointsCollinear(aPoint1, aPoint2, GCS_POINT_WRAPPER(theEntity1));
break;
case CONSTRAINT_MIDDLE_POINT:
aResult = createConstraintMiddlePoint(aPoint1, GCS_EDGE_WRAPPER(theEntity1), aPoint2);
case CONSTRAINT_PT_LINE_DISTANCE:
aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
aPoint1,
- GCS_EDGE_WRAPPER(theEntity1));
+ anEntity1);
break;
case CONSTRAINT_HORIZONTAL_DISTANCE:
case CONSTRAINT_VERTICAL_DISTANCE:
aResult = createConstraintHVDistance(theType, GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
break;
case CONSTRAINT_RADIUS:
- aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
- GCS_EDGE_WRAPPER(theEntity1));
+ aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue), anEntity1);
break;
case CONSTRAINT_ANGLE:
aResult = createConstraintAngle(theConstraint,
GCS_SCALAR_WRAPPER(theValue),
- GCS_EDGE_WRAPPER(theEntity1), GCS_EDGE_WRAPPER(theEntity2));
+ anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
case CONSTRAINT_FIXED:
break;
case CONSTRAINT_HORIZONTAL:
case CONSTRAINT_VERTICAL:
- aResult = createConstraintHorizVert(theType, GCS_EDGE_WRAPPER(theEntity1));
+ aResult = createConstraintHorizVert(theType, anEntity1);
break;
case CONSTRAINT_PARALLEL:
- aResult = createConstraintParallel(GCS_EDGE_WRAPPER(theEntity1),
- GCS_EDGE_WRAPPER(theEntity2));
+ aResult = createConstraintParallel(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
case CONSTRAINT_PERPENDICULAR:
- aResult = createConstraintPerpendicular(GCS_EDGE_WRAPPER(theEntity1),
- GCS_EDGE_WRAPPER(theEntity2));
+ aResult = createConstraintPerpendicular(anEntity1, GCS_EDGE_WRAPPER(theEntity2));
break;
case CONSTRAINT_EQUAL_LINES:
case CONSTRAINT_EQUAL_ELLIPSES:
case CONSTRAINT_EQUAL_LINE_ARC:
case CONSTRAINT_EQUAL_RADIUS:
aResult = createConstraintEqual(theType,
- GCS_EDGE_WRAPPER(theEntity1),
+ anEntity1,
GCS_EDGE_WRAPPER(theEntity2),
anIntermediate);
break;
return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
}
+ConstraintWrapperPtr createConstraintPointsCollinear(
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint3)
+{
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintPointOnLine(
+ *(thePoint1->point()), *(thePoint2->point()), *(thePoint3->point())));
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_ON_CURVE));
+}
+
ConstraintWrapperPtr createConstraintMiddlePoint(
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EdgeWrapper> theEntity,
#include <PlaneGCSSolver_Tools.h>
#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <GeomDataAPI_Point2D.h>
+
#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_ConstraintCoincidenceInternal.h>
+#include <SketchPlugin_Ellipse.h>
+#include <SketchPlugin_EllipticArc.h>
#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
static void getCoincidentFeatureExtremities(const ConstraintPtr& theConstraint,
const StoragePtr& theStorage,
} else if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
theExtremities[0] = theStorage->entity(aFeature->attribute(SketchPlugin_Arc::START_ID()));
theExtremities[1] = theStorage->entity(aFeature->attribute(SketchPlugin_Arc::END_ID()));
+ } else if (aFeature->getKind() == SketchPlugin_EllipticArc::ID()) {
+ theExtremities[0] = theStorage->entity(
+ aFeature->attribute(SketchPlugin_EllipticArc::START_POINT_ID()));
+ theExtremities[1] = theStorage->entity(
+ aFeature->attribute(SketchPlugin_EllipticArc::END_POINT_ID()));
+ }
+ }
+}
+
+static void getPointOwnerAndParent(const AttributeRefAttrPtr theRefAttr,
+ AttributePoint2DPtr& thePoint,
+ FeaturePtr& theOwner,
+ FeaturePtr& theParent)
+{
+ AttributePtr anAttr = theRefAttr->attr();
+ if (theRefAttr->isObject()) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theRefAttr->object());
+ if (anOwner && anOwner->getKind() == SketchPlugin_Point::ID())
+ anAttr = anOwner->attribute(SketchPlugin_Point::COORD_ID());
+ else
+ return;
+ }
+ thePoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+ if (thePoint) {
+ theOwner = ModelAPI_Feature::feature(thePoint->owner());
+ if (theOwner) {
+ std::string aParentRefID;
+ if (theOwner->getKind() == SketchPlugin_Line::ID())
+ aParentRefID = SketchPlugin_Line::PARENT_ID();
+ else if (theOwner->getKind() == SketchPlugin_Point::ID())
+ aParentRefID = SketchPlugin_Point::PARENT_ID();
+ if (!aParentRefID.empty()) {
+ AttributeReferencePtr aParentRef = theOwner->reference(aParentRefID);
+ theParent = aParentRef ? ModelAPI_Feature::feature(aParentRef->value()) : FeaturePtr();
+ }
+ }
+ }
+}
+
+static void ellipseDiameters(FeaturePtr theEllipse,
+ std::pair<std::string, std::string>& theMajorAxis,
+ std::pair<std::string, std::string>& theMinorAxis)
+{
+ if (theEllipse->getKind() == SketchPlugin_Ellipse::ID()) {
+ theMajorAxis.first = SketchPlugin_Ellipse::MAJOR_AXIS_START_ID();
+ theMajorAxis.second = SketchPlugin_Ellipse::MAJOR_AXIS_END_ID();
+ theMinorAxis.first = SketchPlugin_Ellipse::MINOR_AXIS_START_ID();
+ theMinorAxis.second = SketchPlugin_Ellipse::MINOR_AXIS_END_ID();
+ } else if (theEllipse->getKind() == SketchPlugin_EllipticArc::ID()) {
+ theMajorAxis.first = SketchPlugin_EllipticArc::MAJOR_AXIS_START_ID();
+ theMajorAxis.second = SketchPlugin_EllipticArc::MAJOR_AXIS_END_ID();
+ theMinorAxis.first = SketchPlugin_EllipticArc::MINOR_AXIS_START_ID();
+ theMinorAxis.second = SketchPlugin_EllipticArc::MINOR_AXIS_END_ID();
+ }
+}
+
+static void findDiameterOnEllipse(FeaturePtr theConstruction,
+ FeaturePtr theEllipse,
+ AttributePtr& theStart,
+ AttributePtr& theEnd)
+{
+ AttributePtr anEllipseAttr;
+ const std::set<AttributePtr>& aRefs = theConstruction->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
+ aRefIt != aRefs.end(); ++aRefIt) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+ if (anOwner && anOwner->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
+ AttributeRefAttrPtr aRefAttr;
+ if ((*aRefIt)->id() == SketchPlugin_Constraint::ENTITY_A())
+ aRefAttr = anOwner->refattr(SketchPlugin_Constraint::ENTITY_B());
+ else
+ aRefAttr = anOwner->refattr(SketchPlugin_Constraint::ENTITY_A());
+ anEllipseAttr = aRefAttr->attr();
+ break;
}
}
+ if (!anEllipseAttr)
+ return;
+
+ std::pair<std::string, std::string> aMajorAxis, aMinorAxis;
+ ellipseDiameters(theEllipse, aMajorAxis, aMinorAxis);
+ if (anEllipseAttr->id() == aMajorAxis.first) {
+ theStart = anEllipseAttr;
+ theEnd = theEllipse->attribute(aMajorAxis.second);
+ }
+ else if (anEllipseAttr->id() == aMajorAxis.second) {
+ theStart = theEllipse->attribute(aMajorAxis.first);
+ theEnd = anEllipseAttr;
+ }
+ else if (anEllipseAttr->id() == aMinorAxis.first) {
+ theStart = anEllipseAttr;
+ theEnd = theEllipse->attribute(aMinorAxis.second);
+ }
+ else if (anEllipseAttr->id() == aMinorAxis.second) {
+ theStart = theEllipse->attribute(aMinorAxis.first);
+ theEnd = anEllipseAttr;
+ }
+}
+
+static void processEllipticArcExtremities(SketchSolver_ConstraintType& theType,
+ const ConstraintPtr& theConstraint,
+ const StoragePtr& theStorage,
+ std::vector<EntityWrapperPtr>& theAttributes,
+ EntityWrapperPtr theExtremities[2])
+{
+ AttributePoint2DPtr aPointA, aPointB;
+ FeaturePtr anOwnerA, anOwnerB;
+ FeaturePtr aParentA, aParentB;
+ getPointOwnerAndParent(theConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()),
+ aPointA, anOwnerA, aParentA);
+ getPointOwnerAndParent(theConstraint->refattr(SketchPlugin_Constraint::ENTITY_B()),
+ aPointB, anOwnerB, aParentB);
+
+ AttributePtr anAxisStart, anAxisEnd, aPoint;
+ FeaturePtr aConstruction, anEllipticArc;
+ if (aParentA && aParentA == anOwnerB) {
+ aPoint = aPointB;
+ aConstruction = anOwnerA;
+ anEllipticArc = anOwnerB;
+ }
+ else if (aParentB && aParentB == anOwnerA) {
+ aPoint = aPointA;
+ aConstruction = anOwnerB;
+ anEllipticArc = anOwnerA;
+ }
+
+ if (!anEllipticArc || anEllipticArc->getKind() != SketchPlugin_EllipticArc::ID() ||
+ (aPoint->id() != SketchPlugin_EllipticArc::START_POINT_ID() &&
+ aPoint->id() != SketchPlugin_EllipticArc::END_POINT_ID()))
+ return;
+
+ findDiameterOnEllipse(aConstruction, anEllipticArc, anAxisStart, anAxisEnd);
+
+ if (anAxisStart && anAxisEnd) {
+ theAttributes[0] = theStorage->entity(aPoint);
+ theAttributes[1] = theStorage->entity(anAxisStart);
+ theAttributes[2] = theStorage->entity(anAxisEnd);
+ theType = CONSTRAINT_PT_ON_CURVE;
+ getCoincidentFeatureExtremities(theConstraint, theStorage, theExtremities);
+ }
}
return;
}
- if (theAttributes[1])
+ if (theAttributes[1]) {
myType = CONSTRAINT_PT_PT_COINCIDENT;
- else if (theAttributes[2]) {
+ // if elliptic arc boundary point is connected with one of ellipse characteristics,
+ // it should be changed from point-point coincidence to coincidence between point
+ // and axis of the ellipse to decrease only 1 DoF instead of 2 DoF and avoid overconstraint.
+ processEllipticArcExtremities(myType, myBaseConstraint, myStorage,
+ theAttributes, myFeatureExtremities);
+ } else if (theAttributes[2]) {
myType = CONSTRAINT_PT_ON_CURVE;
// obtain extremity points of the coincident feature for further checking of multi-coincidence
getCoincidentFeatureExtremities(myBaseConstraint, myStorage, myFeatureExtremities);
PlaneGCSSolver_UpdateCoincidence* anUpdater =
static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
bool isAccepted = anUpdater->addCoincidence(myAttributes.front(), myAttributes.back());
+ // additionally process internal coincidence, set point coincident with ellipse/elliptic arc
+ // for correct processing further coincidences set by the user
+ if (isAccepted &&
+ myBaseConstraint->getKind() == SketchPlugin_ConstraintCoincidenceInternal::ID()) {
+ AttributeRefAttrPtr aRefAttrA = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ AttributeRefAttrPtr aRefAttrB = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+ if (aRefAttrA && aRefAttrB) {
+ AttributePoint2DPtr anAttrA, anAttrB;
+ FeaturePtr anOwnerA, anOwnerB;
+ FeaturePtr aParentA, aParentB;
+ getPointOwnerAndParent(aRefAttrA, anAttrA, anOwnerA, aParentA);
+ getPointOwnerAndParent(aRefAttrB, anAttrB, anOwnerB, aParentB);
+
+ EntityWrapperPtr aPoint, anEntity;
+ if (aParentA == anOwnerB) {
+ aPoint = myStorage->entity(anAttrA);
+ anEntity = myStorage->entity(anOwnerB);
+ }
+ else if (aParentB == anOwnerA) {
+ aPoint = myStorage->entity(anAttrB);
+ anEntity = myStorage->entity(anOwnerA);
+ }
+ if (aPoint && anEntity)
+ anUpdater->addCoincidence(aPoint, anEntity);
+ }
+ }
// additionally check the point is coincident to extremity of coincident feature
if (myFeatureExtremities[0] && myFeatureExtremities[1]) {