From: azv Date: Mon, 16 Sep 2019 11:33:33 +0000 (+0300) Subject: Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003) X-Git-Tag: V9_4_0a2~4^2~87 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=650554fd6236ddcfdac0a456d1031bf15d411a05;p=modules%2Fshaper.git Task 2.12. New entities: ellipses and arcs of ellipses (issue #3003) * Dump auxiliary objects as features produces by the ellipse. * Unit tests for ellipse creation and movement. --- diff --git a/src/SketchAPI/SketchAPI.i b/src/SketchAPI/SketchAPI.i index 9cde425da..8cbda8d3b 100644 --- a/src/SketchAPI/SketchAPI.i +++ b/src/SketchAPI/SketchAPI.i @@ -44,6 +44,9 @@ %include "std_pair.i" %include "std_shared_ptr.i" +// function with named parameters +%feature("kwargs") SketchAPI_Ellipse::construction; + // shared pointers %shared_ptr(SketchAPI_Arc) %shared_ptr(SketchAPI_MacroArc) diff --git a/src/SketchAPI/SketchAPI_Ellipse.cpp b/src/SketchAPI/SketchAPI_Ellipse.cpp index b601e6612..7b005014e 100644 --- a/src/SketchAPI/SketchAPI_Ellipse.cpp +++ b/src/SketchAPI/SketchAPI_Ellipse.cpp @@ -25,6 +25,14 @@ #include #include +#include +#include +#include + +static const std::string AUXILIARY_VALUE = "aux"; +static const std::string MAJOR_AXIS_ID = "majorAxis"; +static const std::string MINOR_AXIS_ID = "minorAxis"; + SketchAPI_Ellipse::SketchAPI_Ellipse(const std::shared_ptr & theFeature) : SketchAPI_SketchEntity(theFeature) { @@ -149,6 +157,168 @@ ModelHighAPI_Selection SketchAPI_Ellipse::minorAxis() const return ModelHighAPI_Selection(); } +static CompositeFeaturePtr sketchForFeature(FeaturePtr theFeature) +{ + const std::set& aRefs = theFeature->data()->refsToMe(); + for (std::set::const_iterator anIt = aRefs.begin(); anIt != aRefs.end(); ++anIt) + if ((*anIt)->id() == SketchPlugin_Sketch::FEATURES_ID()) + return std::dynamic_pointer_cast((*anIt)->owner()); + return CompositeFeaturePtr(); +} + +static void createInternalConstraint(const CompositeFeaturePtr& theSketch, + const AttributePoint2DPtr& thePoint1, + const AttributePoint2DPtr& thePoint2) +{ + FeaturePtr aConstraint = theSketch->addFeature(SketchPlugin_ConstraintCoincidenceInternal::ID()); + aConstraint->refattr(SketchPlugin_Constraint::ENTITY_A())->setAttr(thePoint1); + aConstraint->refattr(SketchPlugin_Constraint::ENTITY_B())->setAttr(thePoint2); + aConstraint->execute(); +} + +static FeaturePtr createPoint(const CompositeFeaturePtr& theSketch, + const AttributePtr& theCoincident, + const std::string& theAuxOrName) +{ + AttributePoint2DPtr anElPoint = std::dynamic_pointer_cast(theCoincident); + + FeaturePtr aPointFeature = theSketch->addFeature(SketchPlugin_Point::ID()); + AttributePoint2DPtr aCoord = std::dynamic_pointer_cast( + aPointFeature->attribute(SketchPlugin_Point::COORD_ID())); + aCoord->setValue(anElPoint->x(), anElPoint->y()); + aPointFeature->execute(); + + if (theAuxOrName == AUXILIARY_VALUE) + aPointFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true); + else if (!theAuxOrName.empty()) { + aPointFeature->data()->setName(theAuxOrName); + aPointFeature->lastResult()->data()->setName(theAuxOrName); + } + + createInternalConstraint(theSketch, anElPoint, aCoord); + + return aPointFeature; +} + +static FeaturePtr createAxis(const CompositeFeaturePtr& theSketch, + const AttributePtr& theCoincidentStart, + const AttributePtr& theCoincidentEnd, + const std::string& theAuxOrName) +{ + AttributePoint2DPtr aStartPoint = + std::dynamic_pointer_cast(theCoincidentStart); + AttributePoint2DPtr aEndPoint = + std::dynamic_pointer_cast(theCoincidentEnd); + + FeaturePtr aLineFeature = theSketch->addFeature(SketchPlugin_Line::ID()); + AttributePoint2DPtr aLineStart = std::dynamic_pointer_cast( + aLineFeature->attribute(SketchPlugin_Line::START_ID())); + aLineStart->setValue(aStartPoint->x(), aStartPoint->y()); + AttributePoint2DPtr aLineEnd = std::dynamic_pointer_cast( + aLineFeature->attribute(SketchPlugin_Line::END_ID())); + aLineEnd->setValue(aEndPoint->x(), aEndPoint->y()); + aLineFeature->execute(); + + if (theAuxOrName == AUXILIARY_VALUE) + aLineFeature->boolean(SketchPlugin_Point::AUXILIARY_ID())->setValue(true); + else if (!theAuxOrName.empty()) { + aLineFeature->data()->setName(theAuxOrName); + aLineFeature->lastResult()->data()->setName(theAuxOrName); + } + + createInternalConstraint(theSketch, aStartPoint, aLineStart); + createInternalConstraint(theSketch, aEndPoint, aLineEnd); + + return aLineFeature; +} + +std::list > SketchAPI_Ellipse::construction( + const std::string& center, + const std::string& firstFocus, + const std::string& secondFocus, + const std::string& majorAxisStart, + const std::string& majorAxisEnd, + const std::string& minorAxisStart, + const std::string& minorAxisEnd, + const std::string& majorAxis, + const std::string& minorAxis) const +{ + FeaturePtr anEllipse = feature(); + CompositeFeaturePtr aSketch = sketchForFeature(anEllipse); + + std::list anEntities; + if (!center.empty()) { + AttributePtr aCenterAttr = anEllipse->attribute(SketchPlugin_Ellipse::CENTER_ID()); + anEntities.push_back(createPoint(aSketch, aCenterAttr, center)); + } + if (!firstFocus.empty()) { + AttributePtr aFocusAttr = anEllipse->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID()); + anEntities.push_back(createPoint(aSketch, aFocusAttr, firstFocus)); + } + if (!secondFocus.empty()) { + AttributePtr aFocusAttr = anEllipse->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID()); + anEntities.push_back(createPoint(aSketch, aFocusAttr, secondFocus)); + } + if (!majorAxisStart.empty()) { + AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()); + anEntities.push_back(createPoint(aSketch, aStartAttr, majorAxisStart)); + } + if (!majorAxisEnd.empty()) { + AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()); + anEntities.push_back(createPoint(aSketch, aEndAttr, majorAxisEnd)); + } + if (!minorAxisStart.empty()) { + AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()); + anEntities.push_back(createPoint(aSketch, aStartAttr, minorAxisStart)); + } + if (!minorAxisEnd.empty()) { + AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()); + anEntities.push_back(createPoint(aSketch, aEndAttr, minorAxisEnd)); + } + if (!majorAxis.empty()) { + AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID()); + AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()); + anEntities.push_back(createAxis(aSketch, aStartAttr, aEndAttr, majorAxis)); + } + if (!minorAxis.empty()) { + AttributePtr aStartAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_START_ID()); + AttributePtr aEndAttr = anEllipse->attribute(SketchPlugin_Ellipse::MINOR_AXIS_END_ID()); + anEntities.push_back(createAxis(aSketch, aStartAttr, aEndAttr, minorAxis)); + } + + return SketchAPI_SketchEntity::wrap(anEntities); +} + +static void ellipseAttributeAndAuxiliaryFeature( + const FeaturePtr& theInternalConstraint, + std::map& theAttrToFeature) +{ + AttributeRefAttrPtr aRefAttrA = + theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()); + AttributeRefAttrPtr aRefAttrB = + theInternalConstraint->refattr(SketchPlugin_Constraint::ENTITY_B()); + // the first point is usually an ellipse attribute + // and the second point is an attribute of the auxiliary feature + ObjectPtr anAuxObject; + if (aRefAttrB->isObject()) + anAuxObject = aRefAttrB->object(); + else + anAuxObject = aRefAttrB->attr()->owner(); + + FeaturePtr anAuxFeature = ModelAPI_Feature::feature(anAuxObject); + if (anAuxFeature->getKind() == SketchPlugin_Point::ID()) + theAttrToFeature[aRefAttrA->attr()->id()] = anAuxFeature; + else { + const std::string& anAttrID = aRefAttrA->attr()->id(); + if (anAttrID == SketchPlugin_Ellipse::MAJOR_AXIS_START_ID() || + anAttrID == SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()) + theAttrToFeature[MAJOR_AXIS_ID] = anAuxFeature; + else if (anAttrID == SketchPlugin_Ellipse::MINOR_AXIS_START_ID() || + anAttrID == SketchPlugin_Ellipse::MINOR_AXIS_END_ID()) + theAttrToFeature[MINOR_AXIS_ID] = anAuxFeature; + } +} + void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const { if (isCopy()) @@ -168,4 +338,61 @@ void SketchAPI_Ellipse::dump(ModelHighAPI_Dumper& theDumper) const } // dump "auxiliary" flag if necessary SketchAPI_SketchEntity::dump(theDumper); + + // dump auxiliary features produced by ellipse + std::map anAuxFeatures; + const std::set& aRefs = aBase->data()->refsToMe(); + for (std::set::const_iterator aRefIt = aRefs.begin(); + aRefIt != aRefs.end(); ++aRefIt) { + FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner()); + if (anOwner->getKind() != SketchPlugin_ConstraintCoincidenceInternal::ID()) + continue; // process internal constraints only + ellipseAttributeAndAuxiliaryFeature(anOwner, anAuxFeatures); + } + if (!anAuxFeatures.empty()) { + typedef std::pair PairOfStrings; + static PairOfStrings anAttributes[] = { + PairOfStrings(SketchPlugin_Ellipse::CENTER_ID(), "center"), + PairOfStrings(SketchPlugin_Ellipse::FIRST_FOCUS_ID(), "firstFocus"), + PairOfStrings(SketchPlugin_Ellipse::SECOND_FOCUS_ID(), "secondFocus"), + PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID(), "majorAxisStart"), + PairOfStrings(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID(), "majorAxisEnd"), + PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_START_ID(), "minorAxisStart"), + PairOfStrings(SketchPlugin_Ellipse::MINOR_AXIS_END_ID(), "minorAxisEnd"), + PairOfStrings(MAJOR_AXIS_ID, MAJOR_AXIS_ID), + PairOfStrings(MINOR_AXIS_ID, MINOR_AXIS_ID) + }; + + theDumper << "["; + bool isFirst = true; + for (PairOfStrings* anIt = std::begin(anAttributes); + anIt != std::end(anAttributes); ++anIt) { + std::map::iterator aFound = anAuxFeatures.find(anIt->first); + if (aFound == anAuxFeatures.end()) + continue; + if (!isFirst) + theDumper << ", "; + theDumper << theDumper.name(aFound->second, false); + theDumper.doNotDumpFeature(aFound->second); + isFirst = false; + } + theDumper << "] = " << theDumper.name(aBase) << ".construction("; + isFirst = true; + for (PairOfStrings* anIt = std::begin(anAttributes); + anIt != std::end(anAttributes); ++anIt) { + std::map::iterator aFound = anAuxFeatures.find(anIt->first); + if (aFound == anAuxFeatures.end()) + continue; + if (!isFirst) + theDumper << ", "; + isFirst = false; + theDumper << anIt->second << " = \""; + if (aFound->second->boolean(SketchPlugin_SketchEntity::AUXILIARY_ID())->value()) + theDumper << AUXILIARY_VALUE; + else + theDumper << aFound->second->name(); + theDumper << "\""; + } + theDumper << ")" << std::endl; + } } diff --git a/src/SketchAPI/SketchAPI_Ellipse.h b/src/SketchAPI/SketchAPI_Ellipse.h index 13e344369..ee79357c8 100644 --- a/src/SketchAPI/SketchAPI_Ellipse.h +++ b/src/SketchAPI/SketchAPI_Ellipse.h @@ -135,6 +135,22 @@ public: SKETCHAPI_EXPORT ModelHighAPI_Selection minorAxis() const; + /// Create construction elements (focuses, axes etc.). + /// Empty value for each parameter shows that the corresponding feature has been removed. + /// Value "aux" marks this feature as auxiliary. + /// And the name of the feature shows that it is a regular feature. + SKETCHAPI_EXPORT + std::list > construction( + const std::string& center = std::string(), + const std::string& firstFocus = std::string(), + const std::string& secondFocus = std::string(), + const std::string& majorAxisStart = std::string(), + const std::string& majorAxisEnd = std::string(), + const std::string& minorAxisStart = std::string(), + const std::string& minorAxisEnd = std::string(), + const std::string& majorAxis = std::string(), + const std::string& minorAxis = std::string()) const; + /// Dump wrapped feature SKETCHAPI_EXPORT virtual void dump(ModelHighAPI_Dumper& theDumper) const; diff --git a/src/SketchAPI/SketchAPI_Sketch.cpp b/src/SketchAPI/SketchAPI_Sketch.cpp index 4f8b12956..5a329558f 100644 --- a/src/SketchAPI/SketchAPI_Sketch.cpp +++ b/src/SketchAPI/SketchAPI_Sketch.cpp @@ -598,7 +598,7 @@ std::shared_ptr SketchAPI_Sketch::addEllipse( std::shared_ptr aFeature = compositeFeature()->addFeature(SketchPlugin_MacroEllipse::ID()); return MacroEllipsePtr(new SketchAPI_MacroEllipse(aFeature, - thePoint1X, thePoint1Y, thePoint2X, thePoint1Y, thePassedX, thePassedY, isPoint1Center)); + thePoint1X, thePoint1Y, thePoint2X, thePoint2Y, thePassedX, thePassedY, isPoint1Center)); } std::shared_ptr SketchAPI_Sketch::addEllipse( @@ -1093,6 +1093,13 @@ static std::shared_ptr middlePointOnArc(const FeaturePtr& theFeat return std::shared_ptr(new GeomAPI_Pnt2d(x, y)); } +static std::shared_ptr pointOnEllipse(const FeaturePtr& theFeature) +{ + AttributePoint2DPtr aMajorAxisEnd = std::dynamic_pointer_cast( + theFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID())); + return aMajorAxisEnd ? aMajorAxisEnd->pnt() : std::shared_ptr(); +} + static std::shared_ptr middlePoint(const ObjectPtr& theObject) { std::shared_ptr aMiddlePoint; @@ -1108,6 +1115,8 @@ static std::shared_ptr middlePoint(const ObjectPtr& theObject) aMiddlePoint = pointOnCircle(aFeature); else if (aFeatureKind == SketchPlugin_Arc::ID()) aMiddlePoint = middlePointOnArc(aFeature); + else if (aFeatureKind == SketchPlugin_Ellipse::ID()) + aMiddlePoint = pointOnEllipse(aFeature); } return aMiddlePoint; } diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index b304b4aad..80b68f571 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -230,6 +230,9 @@ ADD_UNIT_TESTS( TestCreateCircleByCenterAndPassed.py TestCreateCircleByThreePoints.py TestCreateCircleChangeType.py + TestCreateEllipseByCenterSemiaxisAndPassed.py + TestCreateEllipseByMajorAxisAndPassed.py + TestCreateEllipseByExternal.py TestDegeneratedGeometry.py TestDistanceDump.py TestDistanceSignedVsUnsigned01.py @@ -294,6 +297,7 @@ if(${SKETCHER_CHANGE_RADIUS_WHEN_MOVE}) ADD_UNIT_TESTS( TestMoveArc.py TestMoveCircle.py + TestMoveEllipse.py TestMoveLine.py TestMovementComplex.py TestMovePoint.py diff --git a/src/SketchPlugin/SketchPlugin_Ellipse.cpp b/src/SketchPlugin/SketchPlugin_Ellipse.cpp index af4f1bb4a..098951a85 100644 --- a/src/SketchPlugin/SketchPlugin_Ellipse.cpp +++ b/src/SketchPlugin/SketchPlugin_Ellipse.cpp @@ -77,11 +77,8 @@ void SketchPlugin_Ellipse::execute() // Calculate all characteristics of the ellipse. fillCharacteristicPoints(); - // Make a visible center of the ellipse. - int aResultIndex = 0; - SketchPlugin_Sketch::createPoint2DResult(this, aSketch, CENTER_ID(), aResultIndex++); // Make a visible ellipse. - createEllipse(aSketch, aResultIndex); + createEllipse(aSketch, 0); } bool SketchPlugin_Ellipse::isFixed() { diff --git a/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp b/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp index 2effeb197..fc6e03453 100644 --- a/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp +++ b/src/SketchPlugin/SketchPlugin_MacroEllipse.cpp @@ -244,9 +244,12 @@ void SketchPlugin_MacroEllipse::constraintsForEllipseByCenterAxisAndPassed( this, SECOND_POINT_REF_ID(), theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()), ObjectPtr(), isTangencyApplicable); - SketchPlugin_Tools::createCoincidenceOrTangency( - this, PASSED_POINT_REF_ID(), AttributePtr(), - theEllipseFeature->lastResult(), isTangencyApplicable); + // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object + if (!refattr(PASSED_POINT_REF_ID())->isObject()) { + SketchPlugin_Tools::createCoincidenceOrTangency( + this, PASSED_POINT_REF_ID(), AttributePtr(), + theEllipseFeature->lastResult(), isTangencyApplicable); + } } void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed( @@ -263,9 +266,12 @@ void SketchPlugin_MacroEllipse::constraintsForEllipseByMajoxAxisAndPassed( this, SECOND_POINT_REF_ID(), theEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_END_ID()), ObjectPtr(), isTangencyApplicable); - SketchPlugin_Tools::createCoincidenceOrTangency( - this, PASSED_POINT_REF_ID(), AttributePtr(), - theEllipseFeature->lastResult(), isTangencyApplicable); + // make coincidence only if PASSED_POINT_REF_ID() refers a point but not an object + if (!refattr(PASSED_POINT_REF_ID())->isObject()) { + SketchPlugin_Tools::createCoincidenceOrTangency( + this, PASSED_POINT_REF_ID(), AttributePtr(), + theEllipseFeature->lastResult(), isTangencyApplicable); + } } FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature() @@ -289,6 +295,7 @@ FeaturePtr SketchPlugin_MacroEllipse::createEllipseFeature() aEllipseFeature->execute(); // create auxiliary points + createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::CENTER_ID())); createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::FIRST_FOCUS_ID())); createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::SECOND_FOCUS_ID())); createAuxiliaryPoint(aEllipseFeature->attribute(SketchPlugin_Ellipse::MAJOR_AXIS_START_ID())); diff --git a/src/SketchPlugin/Test/TestCreateEllipseByCenterSemiaxisAndPassed.py b/src/SketchPlugin/Test/TestCreateEllipseByCenterSemiaxisAndPassed.py new file mode 100644 index 000000000..f03f43dc3 --- /dev/null +++ b/src/SketchPlugin/Test/TestCreateEllipseByCenterSemiaxisAndPassed.py @@ -0,0 +1,347 @@ +# Copyright (C) 2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +""" + Test creation of ellipse by center, semi-axis and passed point +""" + +import unittest +from salome.shaper import model + +from GeomAPI import * +from SketchAPI import * + +__updated__ = "2019-09-09" + +class TestEllipse(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myCenter = GeomAPI_Pnt2d(50., 50.) + self.myFocus = GeomAPI_Pnt2d(70., 50.) + self.myPassedPoint = GeomAPI_Pnt2d(60., 60.) + self.myMinorRadius = 20. + self.myDOF = 0 + + def tearDown(self): + self.checkDOF() + model.end() + + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointsEqual(self, thePoint1, thePoint2): + self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5) + self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5) + + def checkPointOnLine(self, theCoordinates, theLine): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + dist = model.distancePointLine(point, theLine) + self.assertAlmostEqual(dist, 0, 7) + + def checkPointOnCircle(self, theCoordinates, theCircle): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + dist = model.distancePointPoint(point, theCircle.center()) + self.assertAlmostEqual(dist , theCircle.radius().value(), 7) + + def checkPointOnEllipse(self, theCoordinates, theEllipse): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y()) + distPF1 = model.distancePointPoint(firstFocus2d, point) + secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y()) + distPF2 = model.distancePointPoint(secondFocus2d, point) + if issubclass(type(theEllipse), SketchAPI_Ellipse): + majorRad = theEllipse.majorRadius().value() + else: + majorRad = theEllipse.majorRadius() + self.assertAlmostEqual(distPF1 + distPF2, 2.0 * majorRad, 7) + + + def test_ellipse_by_center_and_focus(self): + """ Test 1. Create ellipse by coordinates of center, focus and minor radius + """ + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter.x(), self.myCenter.y(), self.myFocus.x(), self.myFocus.y(), self.myMinorRadius) + self.myDOF += 5 + + self.myEllipse2 = self.mySketch.addEllipse(self.myCenter, self.myFocus, self.myMinorRadius) + self.myDOF += 5 + model.do() + + # check both ellipses are equal + anEllipse1 = self.myEllipse1.defaultResult().shape().edge().ellipse() + anEllipse2 = self.myEllipse2.defaultResult().shape().edge().ellipse() + self.checkPointsEqual(anEllipse1.center(), anEllipse2.center()) + self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus()) + self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus()) + self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius()) + self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius()) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 0) + model.testNbSubFeatures(self.mySketch, "SketchLine", 0) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + + def test_ellipse_by_semiaxis_and_passed(self): + """ Test 2. Create ellipse by coordinates of center, major semi-axis point and a passed point on ellipse + """ + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter.x(), self.myCenter.y(), self.myFocus.x(), self.myFocus.y(), self.myPassedPoint.x(), self.myPassedPoint.y(), True) + self.myDOF += 5 + model.do() + anEllipseFeature1 = model.lastSubFeature(self.mySketch, "SketchEllipse") + + self.myEllipse2 = self.mySketch.addEllipse(self.myCenter, self.myFocus, self.myPassedPoint, True) + self.myDOF += 5 + model.do() + anEllipseFeature2 = model.lastSubFeature(self.mySketch, "SketchEllipse") + + # check both ellipses are equal + anEllipse1 = anEllipseFeature1.lastResult().shape().edge().ellipse() + anEllipse2 = anEllipseFeature2.lastResult().shape().edge().ellipse() + self.checkPointsEqual(anEllipse1.center(), anEllipse2.center()) + self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus()) + self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus()) + self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius()) + self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius()) + # check passed point on ellipse + self.checkPointOnEllipse(self.myPassedPoint, anEllipse1) + self.checkPointOnEllipse(self.myPassedPoint, anEllipse2) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 14) + model.testNbSubFeatures(self.mySketch, "SketchLine", 4) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + + def test_ellipse_with_fixed_center(self): + """ Test 3. Create ellipse which center is coincident with another point + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(aLine.endPoint(), self.myFocus, self.myPassedPoint, True) + self.myDOF += 3 + model.do() + # check ellipse + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointsEqual(anEllipse.center(), aLine.endPoint()) + self.checkPointOnEllipse(self.myPassedPoint, anEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_center_on_line(self): + """ Test 4. Create ellipse which center is coincident with a line + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse([self.myCenter, aLine.result()], self.myFocus, self.myPassedPoint, True) + self.myDOF += 4 + model.do() + + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + # check center on line + self.checkPointOnLine(anEllipse.center(), aLine) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_center_on_circle(self): + """ Test 5. Create ellipse which center is coincident with a circle + """ + aCircle = self.mySketch.addCircle(10, 10, 20) + self.myDOF += 3 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse([self.myCenter, aCircle.defaultResult()], self.myFocus, self.myPassedPoint, True) + self.myDOF += 4 + model.do() + + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + # check center on circle + self.checkPointOnCircle(anEllipse.center(), aCircle) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchCircle", 1) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_center_on_ellipse(self): + """ Test 6. Create ellipse which center is coincident with another ellipse + """ + anOtherEllipse = self.mySketch.addEllipse(10, 10, 30, 20, 10) + self.myDOF += 5 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse([self.myCenter, anOtherEllipse.defaultResult()], self.myFocus, self.myPassedPoint, True) + self.myDOF += 4 + model.do() + + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + # check center on ellipse + self.checkPointOnEllipse(anEllipse.center(), anOtherEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_fixed_axis(self): + """ Test 7. Create ellipse which point on major semi-axis is coincident with another point + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, aLine.endPoint(), self.myPassedPoint, True) + self.myDOF += 3 + model.do() + # check ellipse + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(self.myPassedPoint, anEllipse) + self.checkPointOnEllipse(aLine.endPoint(), anEllipse) + # check distance is equal to major semi-axis + dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.endPoint()) + self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_on_line(self): + """ Test 8. Create ellipse which point on major semi-axis is coincident with a line + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, [self.myFocus, aLine.result()], self.myPassedPoint, True) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check axis point on line + self.checkPointOnLine(anEllipse.majorAxisPositive(), aLine) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_on_circle(self): + """ Test 9. Create ellipse which point on major semi-axis is coincident with a circle + """ + aCircle = self.mySketch.addCircle(10, 10, 20) + self.myDOF += 3 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, [self.myFocus, aCircle.defaultResult()], self.myPassedPoint, True) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check center on circle + self.checkPointOnCircle(anEllipse.majorAxisPositive(), aCircle) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchCircle", 1) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_on_ellipse(self): + """ Test 10. Create ellipse which point on major semi-axis is coincident with another ellipse + """ + anOtherEllipse = self.mySketch.addEllipse(10, 10, 90, 40, 30) + self.myDOF += 5 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, [self.myFocus, anOtherEllipse.defaultResult()], self.myPassedPoint, True) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check center on ellipse + self.checkPointOnEllipse(anEllipse.majorAxisPositive(), anOtherEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_fixed_passed_point(self): + """ Test 11. Create ellipse which passed point is coincident with another point + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, self.myFocus, aLine.endPoint(), True) + self.myDOF += 4 + model.do() + # check ellipse + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(aLine.endPoint(), anEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_passed_point_on_line(self): + """ Test 12. Create ellipse which passed point is placed on a line. + Check no constraints is applied. + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myCenter, self.myFocus, [self.myPassedPoint, aLine.result()], True) + self.myDOF += 5 + model.do() + + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(self.myPassedPoint, anEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + # check neither coincidence nor tangent feature exists + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 0) + model.testNbSubFeatures(self.mySketch, "SketchConstraintTangent", 0) + + +if __name__ == "__main__": + test_program = unittest.main(exit=False) + assert test_program.result.wasSuccessful(), "Test failed" + assert model.checkPythonDump() diff --git a/src/SketchPlugin/Test/TestCreateEllipseByExternal.py b/src/SketchPlugin/Test/TestCreateEllipseByExternal.py new file mode 100644 index 000000000..92d33ca3b --- /dev/null +++ b/src/SketchPlugin/Test/TestCreateEllipseByExternal.py @@ -0,0 +1,91 @@ +# Copyright (C) 2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +""" + Test creation of ellipse by external feature +""" + +import unittest +from salome.shaper import model + +from GeomAPI import * +from SketchAPI import * + +__updated__ = "2019-09-12" + +# reference data +CENTER_POINT = GeomAPI_Pnt2d(50., 50.) +FOCUS_POINT = GeomAPI_Pnt2d(70., 60.) +MINOR_RADIUS = 10. + +class TestEllipse(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myDOF = 0 + + def tearDown(self): + self.checkDOF() + model.end() + + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointsEqual(self, thePoint1, thePoint2): + self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5) + self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5) + + + def test_ellipse_by_external_name(self): + """ Test 1. Create ellipse by name of external edge + """ + self.myEllipse = self.mySketch.addEllipse("Sketch_1/SketchEllipse_1") + model.do() + + # check ellipse parameters + anEllipse = self.myEllipse.defaultResult().shape().edge().ellipse() + self.checkPointsEqual(anEllipse.center(), CENTER_POINT) + self.checkPointsEqual(anEllipse.firstFocus(), FOCUS_POINT) + self.assertAlmostEqual(anEllipse.minorRadius(), MINOR_RADIUS) + + def test_ellipse_by_external_selection(self): + """ Test 2. Create ellipse by selected edge + """ + self.myEllipse = self.mySketch.addEllipse(ELLIPSE.results()[-1]) + model.do() + + # check ellipse parameters + anEllipse = self.myEllipse.defaultResult().shape().edge().ellipse() + self.checkPointsEqual(anEllipse.center(), CENTER_POINT) + self.checkPointsEqual(anEllipse.firstFocus(), FOCUS_POINT) + self.assertAlmostEqual(anEllipse.minorRadius(), MINOR_RADIUS) + + +if __name__ == "__main__": + model.begin() + aDocument = model.moduleDocument() + aSketch = model.addSketch(aDocument, model.defaultPlane("XOY")) + ELLIPSE = aSketch.addEllipse(CENTER_POINT, FOCUS_POINT, MINOR_RADIUS) + model.end() + + test_program = unittest.main(exit=False) + assert test_program.result.wasSuccessful(), "Test failed" + assert model.checkPythonDump() diff --git a/src/SketchPlugin/Test/TestCreateEllipseByMajorAxisAndPassed.py b/src/SketchPlugin/Test/TestCreateEllipseByMajorAxisAndPassed.py new file mode 100644 index 000000000..401ab72bf --- /dev/null +++ b/src/SketchPlugin/Test/TestCreateEllipseByMajorAxisAndPassed.py @@ -0,0 +1,319 @@ +# Copyright (C) 2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +""" + Test creation of ellipse by majoraxis and passed point +""" + +import unittest +from salome.shaper import model + +from GeomAPI import * +from SketchAPI import * + +__updated__ = "2019-09-12" + +class TestEllipse(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myAxisStart = GeomAPI_Pnt2d(30., 60.) + self.myAxisEnd = GeomAPI_Pnt2d(80., 50.) + self.myPassedPoint = GeomAPI_Pnt2d(60., 60.) + self.myDOF = 0 + + def tearDown(self): + self.checkDOF() + model.end() + + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointsEqual(self, thePoint1, thePoint2): + self.assertAlmostEqual(thePoint1.x(), thePoint2.x(), 5) + self.assertAlmostEqual(thePoint1.y(), thePoint2.y(), 5) + + def checkPointOnLine(self, theCoordinates, theLine): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + dist = model.distancePointLine(point, theLine) + self.assertAlmostEqual(dist, 0, 7) + + def checkPointOnCircle(self, theCoordinates, theCircle): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + dist = model.distancePointPoint(point, theCircle.center()) + self.assertAlmostEqual(dist , theCircle.radius().value(), 7) + + def checkPointOnEllipse(self, theCoordinates, theEllipse): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y()) + distPF1 = model.distancePointPoint(firstFocus2d, point) + secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y()) + distPF2 = model.distancePointPoint(secondFocus2d, point) + self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius(), 7) + + + def test_ellipse_by_axis_and_passed(self): + """ Test 1. Create ellipse by points defining major semi-axis and a passed point on ellipse + """ + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart.x(), self.myAxisStart.y(), self.myAxisEnd.x(), self.myAxisEnd.y(), self.myPassedPoint.x(), self.myPassedPoint.y(), False) + self.myDOF += 5 + model.do() + anEllipseFeature1 = model.lastSubFeature(self.mySketch, "SketchEllipse") + + self.myEllipse2 = self.mySketch.addEllipse(self.myAxisStart, self.myAxisEnd, self.myPassedPoint, False) + self.myDOF += 5 + model.do() + anEllipseFeature2 = model.lastSubFeature(self.mySketch, "SketchEllipse") + + # check both ellipses are equal + anEllipse1 = anEllipseFeature1.lastResult().shape().edge().ellipse() + anEllipse2 = anEllipseFeature2.lastResult().shape().edge().ellipse() + self.checkPointsEqual(anEllipse1.center(), anEllipse2.center()) + self.checkPointsEqual(anEllipse1.firstFocus(), anEllipse2.firstFocus()) + self.checkPointsEqual(anEllipse1.secondFocus(), anEllipse2.secondFocus()) + self.assertAlmostEqual(anEllipse1.minorRadius(), anEllipse2.minorRadius()) + self.assertAlmostEqual(anEllipse1.majorRadius(), anEllipse2.majorRadius()) + # check passed point on ellipse + self.checkPointOnEllipse(self.myPassedPoint, anEllipse1) + self.checkPointOnEllipse(self.myPassedPoint, anEllipse2) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 14) + model.testNbSubFeatures(self.mySketch, "SketchLine", 4) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + + def test_ellipse_with_fixed_axis_start(self): + """ Test 2. Create ellipse which negative point on the major axis coincident with another point + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(aLine.startPoint(), self.myAxisEnd, self.myPassedPoint, False) + self.myDOF += 3 + model.do() + # check ellipse + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(self.myPassedPoint, anEllipse) + self.checkPointOnEllipse(aLine.startPoint(), anEllipse) + # check distance is equal to major semi-axis + dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.startPoint()) + self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_start_on_line(self): + """ Test 3. Create ellipse which negative point on the major axis coincident with a line + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse([self.myAxisStart, aLine.result()], self.myAxisEnd, self.myPassedPoint, False) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check negative point of major axis on line + self.checkPointOnLine(anEllipse.majorAxisNegative(), aLine) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_start_on_circle(self): + """ Test 4. Create ellipse which negative point on the major axis coincident with a circle + """ + aCircle = self.mySketch.addCircle(10, 10, 20) + self.myDOF += 3 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse([self.myAxisStart, aCircle.defaultResult()], self.myAxisEnd, self.myPassedPoint, False) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check center on circle + self.checkPointOnCircle(anEllipse.majorAxisNegative(), aCircle) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchCircle", 1) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_start_on_ellipse(self): + """ Test 5. Create ellipse which negative point on the major axis coincident with another ellipse + """ + anOtherEllipse = self.mySketch.addEllipse(10, 10, 30, 20, 10) + self.myDOF += 5 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse([self.myAxisStart, anOtherEllipse.defaultResult()], self.myAxisEnd, self.myPassedPoint, False) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check center on ellipse + self.checkPointOnEllipse(anEllipse.majorAxisNegative(), anOtherEllipse.defaultResult().shape().edge().ellipse()) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_fixed_axis_end(self): + """ Test 6. Create ellipse which positive point on the major axis coincident with another point + """ + aLine = self.mySketch.addLine(10, 10, 90, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, aLine.endPoint(), self.myPassedPoint, False) + self.myDOF += 3 + model.do() + # check ellipse + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(self.myPassedPoint, anEllipse) + self.checkPointOnEllipse(aLine.endPoint(), anEllipse) + # check distance is equal to major semi-axis + dist = model.distancePointPoint(GeomAPI_Pnt2d(anEllipse.center().x(), anEllipse.center().y()), aLine.endPoint()) + self.assertAlmostEqual(dist, anEllipse.majorRadius(), 7) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_end_on_line(self): + """ Test 7. Create ellipse which negative point on the major axis coincident with a line + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, [self.myAxisEnd, aLine.result()], self.myPassedPoint, False) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check axis point on line + self.checkPointOnLine(anEllipse.majorAxisPositive(), aLine) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_end_on_circle(self): + """ Test 8. Create ellipse which negative point on the major axis coincident with a circle + """ + aCircle = self.mySketch.addCircle(10, 10, 20) + self.myDOF += 3 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, [self.myAxisEnd, aCircle.defaultResult()], self.myPassedPoint, False) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check center on circle + self.checkPointOnCircle(anEllipse.majorAxisPositive(), aCircle) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchCircle", 1) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_axis_end_on_ellipse(self): + """ Test 9. Create ellipse which negative point on the major axis coincident with another ellipse + """ + anOtherEllipse = self.mySketch.addEllipse(10, 10, 90, 40, 30) + self.myDOF += 5 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, [self.myAxisEnd, anOtherEllipse.defaultResult()], self.myPassedPoint, False) + self.myDOF += 4 + model.do() + + anEllipse = SketchAPI_Ellipse(model.lastSubFeature(self.mySketch, "SketchEllipse")) + # check center on ellipse + self.checkPointOnEllipse(anEllipse.majorAxisPositive(), anOtherEllipse.defaultResult().shape().edge().ellipse()) + # check coincidence feature exists + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 2) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 2) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_fixed_passed_point(self): + """ Test 10. Create ellipse which passed point is coincident with another point + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, self.myAxisEnd, aLine.endPoint(), False) + self.myDOF += 4 + model.do() + # check ellipse + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(aLine.endPoint(), anEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 1) + + def test_ellipse_with_passed_point_on_line(self): + """ Test 11. Create ellipse which passed point is placed on a line. + Check no constraints is applied. + """ + aLine = self.mySketch.addLine(10, 10, 30, 40) + self.myDOF += 4 + model.do() + + self.myEllipse1 = self.mySketch.addEllipse(self.myAxisStart, self.myAxisEnd, [self.myPassedPoint, aLine.result()], False) + self.myDOF += 5 + model.do() + + anEllipseFeature = model.lastSubFeature(self.mySketch, "SketchEllipse") + anEllipse = anEllipseFeature.lastResult().shape().edge().ellipse() + self.checkPointOnEllipse(self.myPassedPoint, anEllipse) + # check number of features + model.testNbSubFeatures(self.mySketch, "SketchPoint", 7) + model.testNbSubFeatures(self.mySketch, "SketchLine", 3) + model.testNbSubFeatures(self.mySketch, "SketchEllipse", 1) + # check neither coincidence nor tangent feature exists + model.testNbSubFeatures(self.mySketch, "SketchConstraintCoincidence", 0) + model.testNbSubFeatures(self.mySketch, "SketchConstraintTangent", 0) + + +if __name__ == "__main__": + test_program = unittest.main(exit=False) + assert test_program.result.wasSuccessful(), "Test failed" + assert model.checkPythonDump() diff --git a/src/SketchPlugin/Test/TestMoveEllipse.py b/src/SketchPlugin/Test/TestMoveEllipse.py new file mode 100644 index 000000000..3795ee82a --- /dev/null +++ b/src/SketchPlugin/Test/TestMoveEllipse.py @@ -0,0 +1,240 @@ +# Copyright (C) 2017-2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +""" + Test movement of the sketch ellipse +""" + +import unittest +import math +from GeomAPI import GeomAPI_Pnt2d +from GeomDataAPI import geomDataAPI_Point2D +from salome.shaper import model + +__updated__ = "2019-09-12" + +class TestMoveEllipse(unittest.TestCase): + def setUp(self): + model.begin() + self.myDocument = model.moduleDocument() + self.mySketch = model.addSketch(self.myDocument, model.defaultPlane("XOY")) + self.myCenter = [70., 50.] + self.myFocus = [100., 70.] + self.myMinorRadius = 20. + self.myEllipse = self.mySketch.addEllipse(self.myCenter[0], self.myCenter[1], self.myFocus[0], self.myFocus[1], self.myMinorRadius) + self.myDOF = 5 + model.do() + self.checkDOF() + self.myMajorRadius = self.myEllipse.majorRadius().value() + + def tearDown(self): + self.checkDOF() + model.end() + + def checkDOF(self): + self.assertEqual(model.dof(self.mySketch), self.myDOF) + + def checkPointCoordinates(self, thePoint, theCoordinates): + aCoord = [] + if issubclass(type(theCoordinates), GeomAPI_Pnt2d): + aCoord = [theCoordinates.x(), theCoordinates.y()] + else: + aCoord = theCoordinates + DIGITS = 7 - math.floor(math.log10(math.hypot(aCoord[0], aCoord[1]))) + self.assertAlmostEqual(thePoint.x(), aCoord[0], DIGITS) + self.assertAlmostEqual(thePoint.y(), aCoord[1], DIGITS) + + def checkPointOnEllipse(self, theCoordinates, theEllipse): + point = GeomAPI_Pnt2d(theCoordinates.x(), theCoordinates.y()) + firstFocus2d = GeomAPI_Pnt2d(theEllipse.firstFocus().x(), theEllipse.firstFocus().y()) + distPF1 = model.distancePointPoint(firstFocus2d, point) + secondFocus2d = GeomAPI_Pnt2d(theEllipse.secondFocus().x(), theEllipse.secondFocus().y()) + distPF2 = model.distancePointPoint(secondFocus2d, point) + self.assertAlmostEqual(distPF1 + distPF2, 2.0 * theEllipse.majorRadius().value(), 7 - math.floor(math.log10(theEllipse.majorRadius().value()))) + + def fixMajorRadius(self): + self.mySketch.setDistance(self.myEllipse.center(), self.myEllipse.majorAxisPositive(), self.myMajorRadius) + self.myDOF -= 1 + model.do() + self.checkDOF() + + def fixMinorRadius(self): + self.mySketch.setDistance(self.myEllipse.center(), self.myEllipse.minorAxisPositive(), self.myMinorRadius) + self.myDOF -= 1 + model.do() + self.checkDOF() + + def fixPoint(self, thePoint): + self.mySketch.setFixed(thePoint) + self.myDOF -= 2 + model.do() + self.checkDOF() + + + def test_move_center_free_ellipse(self): + """ Test 1. Movement of central point of a free ellipse + """ + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), newPosition) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_free_ellipse(self): + """ Test 2. Movement of a free ellipse dragging the edge + """ + newPosition = GeomAPI_Pnt2d(120., 90.) + self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), self.myCenter) + self.checkPointOnEllipse(newPosition, self.myEllipse) + self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_center_ellipse_fixed_major_radius(self): + """ Test 3. Movement of central point of ellipse with fixed major radius + """ + self.fixMajorRadius() + + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), newPosition) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_ellipse_fixed_major_radius(self): + """ Test 4. Movement of ellipse with fixed major radius + """ + self.fixMajorRadius() + + newPosition = GeomAPI_Pnt2d(80., 80.) + self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointOnEllipse(newPosition, self.myEllipse) + self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_center_ellipse_fixed_minor_radius(self): + """ Test 5. Movement of central point of ellipse with fixed minor radius + """ + self.fixMinorRadius() + + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), newPosition) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_ellipse_fixed_minor_radius(self): + """ Test 6. Movement of ellipse with fixed minor radius + """ + self.fixMinorRadius() + + newPosition = GeomAPI_Pnt2d(120., 90.) + self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointOnEllipse(newPosition, self.myEllipse) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_center_ellipse_fixed_center(self): + """ Test 7. Movement of central point of ellipse with fixed center (nothing should be changed) + """ + self.fixPoint(self.myEllipse.center()) + + newPosition = [self.myCenter[0] + 20., self.myCenter[1] + 10.] + self.mySketch.move(self.myEllipse.center(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), self.myCenter) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_ellipse_fixed_center(self): + """ Test 8. Movement of ellipse with fixed center + """ + self.fixPoint(self.myEllipse.center()) + + newPosition = GeomAPI_Pnt2d(120., 90.) + self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointOnEllipse(newPosition, self.myEllipse) + self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_center_ellipse_fixed_focus(self): + """ Test 9. Movement of central point of ellipse with fixed focus + """ + self.fixPoint(self.myEllipse.firstFocus()) + + newPosition = GeomAPI_Pnt2d(self.myCenter[0] + 20., self.myCenter[1] + 10.) + self.mySketch.move(self.myEllipse.center(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), newPosition) + self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus) + self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_focus_ellipse_fixed_focus(self): + """ Test 10. Movement of a focus point of ellipse with fixed focus (nothing should be changed) + """ + self.fixPoint(self.myEllipse.firstFocus()) + + newPosition = GeomAPI_Pnt2d(self.myFocus[0] + 10., self.myFocus[1] + 10.) + self.mySketch.move(self.myEllipse.firstFocus(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertAlmostEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_ellipse_fixed_focus(self): + """ Test 11. Movement of ellipse with fixed focus + """ + self.fixPoint(self.myEllipse.firstFocus()) + + newPosition = GeomAPI_Pnt2d(80., 90.) + self.mySketch.move(self.myEllipse.defaultResult(), newPosition.x(), newPosition.y()) + model.do() + self.checkPointOnEllipse(newPosition, self.myEllipse) + self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus) + self.assertNotEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + self.assertNotEqual(self.myEllipse.majorRadius().value(), self.myMajorRadius) + + def test_move_fixed_ellipse(self): + """ Test 12. Trying to move fully fixed ellipse + """ + self.mySketch.setFixed(self.myEllipse.results()[-1]) + self.myDOF -= 5 + model.do() + self.checkDOF() + + newPosition = [120., 90.] + self.mySketch.move(self.myEllipse.defaultResult(), newPosition[0], newPosition[1]) + model.do() + self.checkPointCoordinates(self.myEllipse.center(), self.myCenter) + self.checkPointCoordinates(self.myEllipse.firstFocus(), self.myFocus) + self.assertAlmostEqual(self.myEllipse.minorRadius().value(), self.myMinorRadius) + + +if __name__ == "__main__": + test_program = unittest.main(exit=False) + assert test_program.result.wasSuccessful(), "Test failed" + assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 9c930341c..1e51edf26 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -966,9 +966,9 @@ - + diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h index e63fa6b91..37aba1bd8 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Defs.h @@ -62,6 +62,7 @@ enum SketchSolver_ConstraintType { CONSTRAINT_PT_PT_COINCIDENT, CONSTRAINT_PT_ON_LINE, CONSTRAINT_PT_ON_CIRCLE, + CONSTRAINT_PT_ON_ELLIPSE, CONSTRAINT_MIDDLE_POINT, CONSTRAINT_DISTANCE, // base distance if we don't know the measured objects yet CONSTRAINT_PT_PT_DISTANCE, diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp index 4e34e8bad..e3d8f790a 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Solver.cpp @@ -21,7 +21,7 @@ #include // Multiplier to correlate IDs of SketchPlugin constraint and primitive PlaneGCS constraints -static const int THE_CONSTRAINT_MULT = 10; +static const int THE_CONSTRAINT_MULT = 100; PlaneGCSSolver_Solver::PlaneGCSSolver_Solver() diff --git a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp index 5b3572c02..d0914df1c 100644 --- a/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp +++ b/src/SketchSolver/PlaneGCSSolver/PlaneGCSSolver_Tools.cpp @@ -192,6 +192,7 @@ ConstraintWrapperPtr PlaneGCSSolver_Tools::createConstraint( break; case CONSTRAINT_PT_ON_LINE: case CONSTRAINT_PT_ON_CIRCLE: + case CONSTRAINT_PT_ON_ELLIPSE: aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_EDGE_WRAPPER(theEntity1)); break; case CONSTRAINT_MIDDLE_POINT: diff --git a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp index 9903b850e..f1c32b733 100644 --- a/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp +++ b/src/SketchSolver/SketchSolver_ConstraintCoincidence.cpp @@ -102,6 +102,8 @@ void SketchSolver_ConstraintCoincidence::getAttributes( myType = CONSTRAINT_PT_ON_LINE; else if (anEntType == ENTITY_CIRCLE || anEntType == ENTITY_ARC) myType = CONSTRAINT_PT_ON_CIRCLE; + else if (anEntType == ENTITY_ELLIPSE || anEntType == ENTITY_ELLIPTICAL_ARC) + myType = CONSTRAINT_PT_ON_ELLIPSE; else myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE(); diff --git a/src/SketcherPrs/SketcherPrs_LengthDimension.cpp b/src/SketcherPrs/SketcherPrs_LengthDimension.cpp index 2eecd66c1..b895b6d6b 100644 --- a/src/SketcherPrs/SketcherPrs_LengthDimension.cpp +++ b/src/SketcherPrs/SketcherPrs_LengthDimension.cpp @@ -205,6 +205,9 @@ bool SketcherPrs_LengthDimension::readyToDisplay(ModelAPI_Feature* theConstraint const std::shared_ptr& thePlane, gp_Pnt& thePnt1, gp_Pnt& thePnt2) { + if (!thePlane) + return false; + DataPtr aData = theConstraint->data(); if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) { // The constraint is length