From 3bdd5eae1e9e7da4828cc18a65eaddc8cfa34c77 Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 22 Mar 2017 10:05:21 +0300 Subject: [PATCH] Issue #2024: Redesign of circle and arc of circle: Unit tests for creation of a circle by different mode --- src/PythonAPI/model/tests/tests.py | 14 + src/SketchPlugin/CMakeLists.txt | 5 +- ...estSketchArcCircle.py => TestCreateArc.py} | 51 +-- .../Test/TestCreateCircleByCenterAndPassed.py | 260 +++++++++++++++ .../Test/TestCreateCircleByThreePoints.py | 306 ++++++++++++++++++ .../Test/TestCreateCircleChangeType.py | 171 ++++++++++ src/SketchPlugin/plugin-Sketch.xml | 3 + 7 files changed, 760 insertions(+), 50 deletions(-) rename src/SketchPlugin/Test/{TestSketchArcCircle.py => TestCreateArc.py} (79%) create mode 100644 src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py create mode 100644 src/SketchPlugin/Test/TestCreateCircleByThreePoints.py create mode 100644 src/SketchPlugin/Test/TestCreateCircleChangeType.py diff --git a/src/PythonAPI/model/tests/tests.py b/src/PythonAPI/model/tests/tests.py index 88e0731d4..68b766385 100644 --- a/src/PythonAPI/model/tests/tests.py +++ b/src/PythonAPI/model/tests/tests.py @@ -1,5 +1,6 @@ from GeomAlgoAPI import * from GeomAPI import * +from ModelAPI import ModelAPI_Feature import math @@ -139,3 +140,16 @@ def testHaveNamingFaces(theFeature, theModel, thePartDoc) : name = attrSelection.namingName() assert(shape.isFace()) assert(name != ""), "String empty" + +def testNbSubFeatures(theComposite, theKindOfSub, theExpectedCount): + """ Tests number of sub-features of the given type + :param theComposite composite feature to check its subs + :param theKindOfSub kind of sub-feature to calculate count + :param theExpectedCount expected number of sub-features + """ + count = 0 + for aSub in theComposite.features().list(): + aFeature = ModelAPI_Feature.feature(aSub) + if aFeature is not None and aFeature.getKind() == theKindOfSub: + count += 1 + assert (count == theExpectedCount), "Number of sub-features of type {}: {}, expected {}".format(theKindOfSub, count, theExpectedCount) diff --git a/src/SketchPlugin/CMakeLists.txt b/src/SketchPlugin/CMakeLists.txt index 5cc31d85b..614dd0d29 100644 --- a/src/SketchPlugin/CMakeLists.txt +++ b/src/SketchPlugin/CMakeLists.txt @@ -123,7 +123,10 @@ INSTALL(DIRECTORY icons/ DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}/icons/Sketc INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES}) ADD_UNIT_TESTS(TestSketchPointLine.py - TestSketchArcCircle.py + TestCreateArc.py + TestCreateCircleByCenterAndPassed.py + TestCreateCircleByThreePoints.py + TestCreateCircleChangeType.py TestConstraintCoincidence.py TestConstraintCollinear.py TestConstraintLength.py diff --git a/src/SketchPlugin/Test/TestSketchArcCircle.py b/src/SketchPlugin/Test/TestCreateArc.py similarity index 79% rename from src/SketchPlugin/Test/TestSketchArcCircle.py rename to src/SketchPlugin/Test/TestCreateArc.py index 677de24e5..936981dbf 100644 --- a/src/SketchPlugin/Test/TestSketchArcCircle.py +++ b/src/SketchPlugin/Test/TestCreateArc.py @@ -1,6 +1,6 @@ """ - TestSketchArcCircle.py - + TestCreateArc.py + static const std::string MY_SKETCH_ARC_ID("SketchArc"); static const std::string MY_CENTER_ID = "ArcCenter"; static const std::string MY_START_ID = "ArcStartPoint"; @@ -8,12 +8,6 @@ data()->addAttribute(SketchPlugin_Arc::CENTER_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(SketchPlugin_Arc::START_ID(), GeomDataAPI_Point2D::typeId()); data()->addAttribute(SketchPlugin_Arc::END_ID(), GeomDataAPI_Point2D::typeId()); - - static const std::string MY_CIRCLE_ID("SketchCircle"); - static const std::string MY_CIRCLE_CENTER_ID("CircleCenter"); - static const std::string MY_CIRCLE_RADIUS_ID("CircleRadius"); - data()->addAttribute(SketchPlugin_Circle::CENTER_ID(), GeomDataAPI_Point2D::typeId()); - data()->addAttribute(SketchPlugin_Circle::RADIUS_ID(), ModelAPI_AttributeDouble::typeId()); """ #========================================================================= @@ -159,47 +153,6 @@ aShape = aResultConstruction.shape() assert (aShape is not None) assert (not aShape.isNull()) #========================================================================= -# Create a circle -# 1. Test SketchPlugin_Circle.h attributes -# 2. ModelAPI_AttributeDouble attribute -#========================================================================= -aSession.startOperation() -aSketchReflist = aSketchFeature.reflist("Features") -# Arc is already added -assert (aSketchReflist.size() == 1) -assert (len(aSketchReflist.list()) == 1) -aSketchCircle = aSketchFeature.addFeature("SketchCircle") -assert (aSketchCircle.getKind() == "SketchCircle") -anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter")) -assert (not anCircleCentr.isInitialized()) -aCircleRadius = aSketchCircle.real("CircleRadius") -assert (type(aCircleRadius) == ModelAPI_AttributeDouble) -# ModelAPI_AttributeDouble.typeId() is checked in ModelAPI_TestConstants -assert (aCircleRadius.attributeType() == ModelAPI_AttributeDouble.typeId()) -anCircleCentr.setValue(-25., -25) -aCircleRadius.setValue(25.) -assert (anCircleCentr.x() == -25) -assert (anCircleCentr.y() == -25) -assert (aCircleRadius.value() == 25) -aSession.finishOperation() -#========================================================================= -# Edit the Cricle -# 1. Check that changing the centr of a circle does not affects radius -# 2. and vise versa; also check that int is acceptable as well as a real -#========================================================================= -aSession.startOperation() -anCircleCentr.setValue(10, 60) -aSession.finishOperation() -assert (anCircleCentr.x() == 10) -assert (anCircleCentr.y() == 60) -assert (aCircleRadius.value() == 25) -aSession.startOperation() -aCircleRadius.setValue(int(20)) -aSession.finishOperation() -assert (anCircleCentr.x() == 10) -assert (anCircleCentr.y() == 60) -assert (aCircleRadius.value() == 20) -#========================================================================= # Create an arc, tangent to the line #========================================================================= aSession.startOperation() diff --git a/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py b/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py new file mode 100644 index 000000000..e6695c852 --- /dev/null +++ b/src/SketchPlugin/Test/TestCreateCircleByCenterAndPassed.py @@ -0,0 +1,260 @@ +""" + TestCreateCircleByCenterAndPassed.py + + Test creation methods of a circle built by a center and a passed point +""" + +#========================================================================= +# Initialization of the test +#========================================================================= +from GeomDataAPI import * +from GeomAPI import * +from ModelAPI import * +from SketchAPI import SketchAPI_Sketch +from salome.shaper import model +import math + +__updated__ = "2017-03-22" + + +#========================================================================= +# Auxiliary functions +#========================================================================= +TOLERANCE = 1.e-7 + +def getLastCircle(theSketch): + """ + obtains last feature from the sketch and generates error if the feature is not a circle + """ + expectedKind = "SketchCircle" + for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1): + aSub = theSketch.subFeature(anIndex) + if (aSub.getKind() == expectedKind): + return aSub + +def verifyLastCircle(theSketch, theX, theY, theR): + """ + subroutine to verify position of last circle in the sketch + """ + aLastCircle = getLastCircle(theSketch) + aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center")) + verifyPointCoordinates(aCenter, theX, theY) + aRadius = aLastCircle.real("circle_radius") + assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR) + +def verifyPointCoordinates(thePoint, theX, theY): + assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY) + +def verifyPointOnLine(thePoint, theLine): + aDistance = distancePointLine(thePoint, theLine) + assert aDistance < TOLERANCE, "Point is not on Line, distance: {0}".format(aDistance) + +def verifyTangentCircles(theCircle1, theCircle2): + aCenter1 = geomDataAPI_Point2D(theCircle1.attribute("circle_center")) + aCenter2 = geomDataAPI_Point2D(theCircle2.attribute("circle_center")) + aDistCC = distancePointPoint(aCenter1, aCenter2) + aRadius1 = theCircle1.real("circle_radius").value() + aRadius2 = theCircle2.real("circle_radius").value() + aRSum = aRadius1 + aRadius2 + aRDiff = math.fabs(aRadius1 - aRadius2) + assert math.fabs(aRSum - aDistCC) < TOLERANCE or math.fabs(aRDiff - aDistCC) < TOLERANCE, "Circles do not tangent" + +def distancePointPoint(thePoint1, thePoint2): + return thePoint1.pnt().distance(thePoint2.pnt()) + +def distancePointLine(thePoint, theLine): + aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy() + aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy() + aLineDir = aLineEnd.decreased(aLineStart) + aLineLen = aLineEnd.distance(aLineStart) + aPntDir = thePoint.pnt().xy().decreased(aLineStart) + return math.fabs(aPntDir.cross(aLineDir) / aLineLen) + + +#========================================================================= +# Start of test +#========================================================================= + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = featureToCompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +aSketch = SketchAPI_Sketch(aSketchFeature) + +#========================================================================= +# Test 1. Create a circle by center and radius +#========================================================================= +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchCircle") +assert (aCircle.getKind() == "SketchCircle") +aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center")) +assert (not aCircleCenter.isInitialized()) +aCircleRadius = aCircle.real("circle_radius") +assert (type(aCircleRadius) == ModelAPI_AttributeDouble) +# ModelAPI_AttributeDouble.typeId() is checked in ModelAPI_TestConstants +assert (aCircleRadius.attributeType() == ModelAPI_AttributeDouble.typeId()) +aCircleCenter.setValue(-25., -25) +aCircleRadius.setValue(25.) +aSession.finishOperation() +verifyLastCircle(aSketchFeature, -25., -25., 25.) +#========================================================================= +# Edit the Circle +# 1. check that changing the center of a circle does not affect radius and vise versa +# 2. also check that int is acceptable as well as a real +#========================================================================= +aSession.startOperation() +aCircleCenter.setValue(10, 60) +aSession.finishOperation() +verifyLastCircle(aSketchFeature, 10., 60., 25.) +aSession.startOperation() +aCircleRadius.setValue(int(20)) +aSession.finishOperation() +verifyLastCircle(aSketchFeature, 10., 60., 20.) + +#========================================================================= +# Test 2. Create a circle as a macro-feature by center and passed point +#========================================================================= +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +assert (aCircle.getKind() == "SketchMacroCircle") +aCircleCenter = geomDataAPI_Point2D(aCircle.attribute("center_point")) +assert (not aCircleCenter.isInitialized()) +aCirclePassed = geomDataAPI_Point2D(aCircle.attribute("passed_point")) +assert (not aCirclePassed.isInitialized()) +aCircleType = aCircle.string("circle_type") +assert (not aCircleType.isInitialized()) +aCircleType.setValue("circle_type_by_center_and_passed_points") +aCircleCenter.setValue(-25., -25) +aCirclePassed.setValue(0., -25.) +aRadius = distancePointPoint(aCircleCenter, aCirclePassed) +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 2) +verifyLastCircle(aSketchFeature, -25., -25., aRadius) + +#========================================================================= +# Test 3. Create a circle as a macro-feature by center and passed point coincident to other points +#========================================================================= +# get previous circle +aPrevCircle = getLastCircle(aSketchFeature) +aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center")) +# create additional point +aPointCoodinates = [0., 0.] +aSession.startOperation() +aPoint = aSketchFeature.addFeature("SketchPoint") +aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordindates")) +aPointCoord.setValue(aPointCoodinates[0], aPointCoodinates[1]) +aSession.finishOperation() +# create new circle +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCenter = geomDataAPI_Point2D(aCircle.attribute("center_point")) +aCenterRef = aCircle.refattr("center_point_ref") +assert (not aCenterRef.isInitialized()) +aPassed = geomDataAPI_Point2D(aCircle.attribute("passed_point")) +aPassedRef = aCircle.refattr("passed_point_ref") +assert (not aPassedRef.isInitialized()) +aCircleType = aCircle.string("circle_type") +assert (not aCircleType.isInitialized()) +# initialize attributes +aCircleType.setValue("circle_type_by_center_and_passed_points") +aCenterRef.setObject(aPoint.lastResult()) +aCenter.setValue(aPointCoord.pnt()) +aPassedRef.setAttr(aPrevCenter) +aPassed.setValue(aPrevCenter.pnt()) +aRadius = distancePointPoint(aPrevCenter, aPointCoord) +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 6) +verifyPointCoordinates(aPointCoord, aPointCoodinates[0], aPointCoodinates[1]) +verifyLastCircle(aSketchFeature, aPointCoord.x(), aPointCoord.y(), aRadius) +model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 2) + +#========================================================================= +# Test 4. Create a circle as a macro-feature by center on a line and passed point on another circle +#========================================================================= +# get previous circle +aPrevCircle = getLastCircle(aSketchFeature) +aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center")) +aPrevCenterXY = [aPrevCenter.x(), aPrevCenter.y()] +aPrevRadius = aPrevCircle.real("circle_radius").value() +# create additional line +aLineStart = [10., 0.] +aLineEnd = [10., 50.] +aSession.startOperation() +aLine = aSketchFeature.addFeature("SketchLine") +aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint")) +aStartPnt.setValue(aLineStart[0], aLineStart[1]) +aEndPnt = geomDataAPI_Point2D(aLine.attribute("EndPoint")) +aEndPnt.setValue(aLineEnd[0], aLineEnd[1]) +aSession.finishOperation() +# create new circle +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCenter = geomDataAPI_Point2D(aCircle.attribute("center_point")) +aCenterRef = aCircle.refattr("center_point_ref") +aPassed = geomDataAPI_Point2D(aCircle.attribute("passed_point")) +aPassedRef = aCircle.refattr("passed_point_ref") +aCircleType = aCircle.string("circle_type") +# initialize attributes +aCircleType.setValue("circle_type_by_center_and_passed_points") +aCenterRef.setObject(aLine.lastResult()) +anExpectedCenter = [(aLineStart[0] + aLineEnd[0]) * 0.5, (aLineStart[1] + aLineEnd[1]) * 0.5] +aCenter.setValue(anExpectedCenter[0], anExpectedCenter[1]) +aPassedRef.setObject(aPrevCircle.lastResult()) +aPassed.setValue(aPrevCenter.x() + aPrevRadius, aPrevCenter.y()) +aRadius = distancePointPoint(aCenter, aPassed) +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 10) +# check connected features do not change their positions +verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1]) +assert(aPrevCircle.real("circle_radius").value() == aPrevRadius) +verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1]) +verifyPointCoordinates(aEndPnt, aLineEnd[0], aLineEnd[1]) +# verify newly created circle +aCircle = getLastCircle(aSketchFeature) +aCenter = geomDataAPI_Point2D(aCircle.attribute("circle_center")) +verifyPointCoordinates(aCenter, anExpectedCenter[0], anExpectedCenter[1]) +verifyPointOnLine(aCenter, aLine) +verifyTangentCircles(aCircle, aPrevCircle) +model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3) +model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 1) + +#========================================================================= +# Test 5. Create a circle as a macro-feature by center and passed point placed on the same line +# Check the circle is not created +#========================================================================= +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCenter = geomDataAPI_Point2D(aCircle.attribute("center_point")) +aCenterRef = aCircle.refattr("center_point_ref") +aPassed = geomDataAPI_Point2D(aCircle.attribute("passed_point")) +aPassedRef = aCircle.refattr("passed_point_ref") +aCircleType = aCircle.string("circle_type") +# initialize attributes +aCircleType.setValue("circle_type_by_center_and_passed_points") +aCenterRef.setObject(aLine.lastResult()) +aCenter.setValue(anExpectedCenter[0], anExpectedCenter[1]) +aPassedRef.setObject(aLine.lastResult()) +aPassed.setValue(aLineStart[0], aLineStart[1]) +aSession.finishOperation() +aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1) +assert aLastFeature == aCircle, "ERROR: SketchMacroCircle has NOT expected to be valid" +aDocument.removeFeature(aCircle) +assert (aSketchFeature.numberOfSubs() == 10) + +#========================================================================= +# End of test +#========================================================================= + +from salome.shaper import model +assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py b/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py new file mode 100644 index 000000000..22f70e6ed --- /dev/null +++ b/src/SketchPlugin/Test/TestCreateCircleByThreePoints.py @@ -0,0 +1,306 @@ +""" + TestCreateCircleByThreePoints.py + + Test creation methods of a circle built by three points +""" + +#========================================================================= +# Initialization of the test +#========================================================================= +from GeomDataAPI import * +from GeomAPI import * +from ModelAPI import * +from SketchAPI import SketchAPI_Sketch +from salome.shaper import model +import math + +__updated__ = "2017-03-22" + + +#========================================================================= +# Auxiliary functions +#========================================================================= +TOLERANCE = 1.e-7 + +def getLastCircle(theSketch): + """ + obtains last feature from the sketch and generates error if the feature is not a circle + """ + expectedKind = "SketchCircle" + for anIndex in range(theSketch.numberOfSubs() - 1, -1, -1): + aSub = theSketch.subFeature(anIndex) + if (aSub.getKind() == expectedKind): + return aSub + +def verifyLastCircle(theSketch, theX, theY, theR): + """ + subroutine to verify position of last circle in the sketch + """ + aLastCircle = getLastCircle(theSketch) + aCenter = geomDataAPI_Point2D(aLastCircle.attribute("circle_center")) + verifyPointCoordinates(aCenter, theX, theY) + aRadius = aLastCircle.real("circle_radius") + assert aRadius.value() == theR, "Wrong radius {0}, expected {1}".format(aRadius.value(), theR) + +def verifyPointCoordinates(thePoint, theX, theY): + assert thePoint.x() == theX and thePoint.y() == theY, "Wrong '{0}' point ({1}, {2}), expected ({3}, {4})".format(thePoint.attributeType(), thePoint.x(), thePoint.y(), theX, theY) + +def verifyPointOnCircle(thePoint, theCircle): + aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center")) + aDistCP = distancePointPoint(aCircleCenter, thePoint) + aCircleRadius = theCircle.real("circle_radius").value() + assert math.fabs(aDistCP - aCircleRadius) < TOLERANCE, "Point is not on circle, distance: {0}, radius of circle: {1}".format(aDistCP, aCircleRadius) + +def verifyTangentCircles(theCircle1, theCircle2): + aCenter1 = geomDataAPI_Point2D(theCircle1.attribute("circle_center")) + aCenter2 = geomDataAPI_Point2D(theCircle2.attribute("circle_center")) + aDistCC = distancePointPoint(aCenter1, aCenter2) + aRadius1 = theCircle1.real("circle_radius").value() + aRadius2 = theCircle2.real("circle_radius").value() + verifyTangentCircular(aDistCC, aRadius1, aRadius2) + +def verifyTangentCircleArc(theCircle, theArc): + aCircleCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center")) + anArcCenter = geomDataAPI_Point2D(theArc.attribute("ArcCenter")) + anArcStart = geomDataAPI_Point2D(theArc.attribute("ArcStartPoint")) + aDistCC = distancePointPoint(aCircleCenter, anArcCenter) + aCircleRadius = theCircle.real("circle_radius").value() + anArcRadius = distancePointPoint(anArcCenter, anArcStart) + verifyTangentCircular(aDistCC, aCircleRadius, anArcRadius) + +def verifyTangentCircular(theDistBetweenCenters, theRadius1, theRadius2): + aRSum = theRadius1 + theRadius2 + aRDiff = math.fabs(theRadius1 - theRadius2) + assert math.fabs(aRSum - theDistBetweenCenters) < TOLERANCE or math.fabs(aRDiff - theDistBetweenCenters) < TOLERANCE, "Two circulars are not tangent" + +def verifyTangentCircleLine(theCircle, theLine): + aCenter = geomDataAPI_Point2D(theCircle.attribute("circle_center")) + aRadius = theCircle.real("circle_radius").value() + aDistCL = distancePointLine(aCenter, theLine) + assert math.fabs(aDistCL - aRadius) < TOLERANCE, "Circle and line are not tangent" + +def distancePointPoint(thePoint1, thePoint2): + return thePoint1.pnt().distance(thePoint2.pnt()) + +def distancePointLine(thePoint, theLine): + aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint")).pnt().xy() + aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint")).pnt().xy() + aLineDir = aLineEnd.decreased(aLineStart) + aLineLen = aLineEnd.distance(aLineStart) + aPntDir = thePoint.pnt().xy().decreased(aLineStart) + return math.fabs(aPntDir.cross(aLineDir) / aLineLen) + + +#========================================================================= +# Start of test +#========================================================================= + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = featureToCompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +aSketch = SketchAPI_Sketch(aSketchFeature) + +#========================================================================= +# Test 1. Create a circle by three points +#========================================================================= +expectedCenter = [0., 0.] +expectedRadius = 10. +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +assert (aCircle.getKind() == "SketchMacroCircle") +aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point")) +assert (not aCirclePnt1.isInitialized()) +assert (not aCirclePnt2.isInitialized()) +assert (not aCirclePnt3.isInitialized()) +aCircleType = aCircle.string("circle_type") +assert (not aCircleType.isInitialized()) +aCircleType.setValue("circle_type_by_three_points") +aCirclePnt1.setValue(expectedCenter[0] - expectedRadius, expectedCenter[1]) +aCirclePnt2.setValue(expectedCenter[0] + expectedRadius, expectedCenter[1]) +aCirclePnt3.setValue(expectedCenter[0], expectedCenter[1] + expectedRadius) +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 1) +verifyLastCircle(aSketchFeature, expectedCenter[0], expectedCenter[1], expectedRadius) + +#========================================================================= +# Test 2. Create a circle by three points coincident to other points +#========================================================================= +# get previous circle +aPrevCircle = getLastCircle(aSketchFeature) +aPrevCenter = geomDataAPI_Point2D(aPrevCircle.attribute("circle_center")) +aPrevCenterXY = [aPrevCenter.x(), aPrevCenter.y()] +aPrevCircleRadius = aPrevCircle.real("circle_radius").value() +# create additional point and line +aPointCoodinates = [5., 20.] +aLineStart = [10., 0.] +aLineEnd = [10., 50.] +aSession.startOperation() +aPoint = aSketchFeature.addFeature("SketchPoint") +aPointCoord = geomDataAPI_Point2D(aPoint.attribute("PointCoordindates")) +aPointCoord.setValue(aPointCoodinates[0], aPointCoodinates[1]) +aLine = aSketchFeature.addFeature("SketchLine") +aStartPnt = geomDataAPI_Point2D(aLine.attribute("StartPoint")) +aStartPnt.setValue(aLineStart[0], aLineStart[1]) +aEndPnt = geomDataAPI_Point2D(aLine.attribute("EndPoint")) +aEndPnt.setValue(aLineEnd[0], aLineEnd[1]) +aSession.finishOperation() +# create new circle +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point")) +aCirclePnt1Ref = aCircle.refattr("first_point_ref") +aCirclePnt2Ref = aCircle.refattr("second_point_ref") +aCirclePnt3Ref = aCircle.refattr("third_point_ref") +aCircleType = aCircle.string("circle_type") +# initialize attributes +aCircleType.setValue("circle_type_by_three_points") +aCirclePnt1Ref.setAttr(aPrevCenter) +aCirclePnt1.setValue(aPrevCenter.pnt()) +aCirclePnt2Ref.setObject(aPoint.lastResult()) +aCirclePnt2.setValue(aPointCoord.pnt()) +aCirclePnt3Ref.setAttr(aStartPnt) +aCirclePnt3.setValue(aLineStart[0], aLineStart[1]) +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 7) +# check the points do not change their positions +verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1]) +verifyPointCoordinates(aPointCoord, aPointCoodinates[0], aPointCoodinates[1]) +verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1]) +# check newly created circle passes through the points +aCircle = getLastCircle(aSketchFeature) +verifyPointOnCircle(aPrevCenter, aCircle) +verifyPointOnCircle(aPointCoord, aCircle) +verifyPointOnCircle(aStartPnt, aCircle) +model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3) +model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 0) + +#========================================================================= +# Test 3. Create a circle by three points and tangent to line, circle and arc +#========================================================================= +# create additional arc +anArcRadius = 5. +anArcCenter = [-10., 10.] +anArcStart = [anArcCenter[0], anArcCenter[1] - anArcRadius] +anArcEnd = [anArcCenter[0], anArcCenter[1] + anArcRadius] +aSession.startOperation() +anArc = aSketchFeature.addFeature("SketchArc") +anArcCenterPnt = geomDataAPI_Point2D(anArc.attribute("ArcCenter")) +anArcCenterPnt.setValue(anArcCenter[0], anArcCenter[1]) +anArcStartPnt = geomDataAPI_Point2D(anArc.attribute("ArcStartPoint")) +anArcStartPnt.setValue(anArcStart[0], anArcStart[1]) +anArcEndPnt = geomDataAPI_Point2D(anArc.attribute("ArcEndPoint")) +anArcEndPnt.setValue(anArcEnd[0], anArcEnd[1]) +aSession.finishOperation() +# create new circle +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point")) +aCirclePnt1Ref = aCircle.refattr("first_point_ref") +aCirclePnt2Ref = aCircle.refattr("second_point_ref") +aCirclePnt3Ref = aCircle.refattr("third_point_ref") +aCircleType = aCircle.string("circle_type") +# initialize attributes +aCircleType.setValue("circle_type_by_three_points") +aCirclePnt1Ref.setObject(aPrevCircle.lastResult()) +aCirclePnt1.setValue(aPrevCenter.x(), aPrevCenter.y() + aPrevCircleRadius) +aCirclePnt2Ref.setObject(aLine.lastResult()) +aCirclePnt2.setValue(aLineEnd[0], aLineEnd[1]) +aCirclePnt3Ref.setObject(anArc.lastResult()) +aCirclePnt3.setValue(anArcCenter[0] + anArcRadius, anArcCenter[1]) +aSession.finishOperation() +assert (aSketchFeature.numberOfSubs() == 12) +# check the tangent entities do not change their positions +verifyPointCoordinates(aPrevCenter, aPrevCenterXY[0], aPrevCenterXY[1]) +assert (aPrevCircle.real("circle_radius").value() == aPrevCircleRadius) +verifyPointCoordinates(aStartPnt, aLineStart[0], aLineStart[1]) +verifyPointCoordinates(aEndPnt, aLineEnd[0], aLineEnd[1]) +verifyPointCoordinates(anArcCenterPnt, anArcCenter[0], anArcCenter[1]) +verifyPointCoordinates(anArcStartPnt, anArcStart[0], anArcStart[1]) +verifyPointCoordinates(anArcEndPnt, anArcEnd[0], anArcEnd[1]) +# check newly created circle passes through the points +aCircle = getLastCircle(aSketchFeature) +verifyTangentCircles(aCircle, aPrevCircle) +verifyTangentCircleArc(aCircle, anArc) +verifyTangentCircleLine(aCircle, aLine) +model.testNbSubFeatures(aSketch, "SketchConstraintCoincidence", 3) +model.testNbSubFeatures(aSketch, "SketchConstraintTangent", 3) + +#========================================================================= +# Test 4. Create a circle by three points: +# a. first two points are coincident to extremities of the line +# b. check that this line is not selectable by third point +#========================================================================= +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point")) +aCirclePnt1Ref = aCircle.refattr("first_point_ref") +aCirclePnt2Ref = aCircle.refattr("second_point_ref") +aCirclePnt3Ref = aCircle.refattr("third_point_ref") +aCircleType = aCircle.string("circle_type") +# initialize attributes +aCircleType.setValue("circle_type_by_three_points") +aCirclePnt1Ref.setAttr(aStartPnt) +aCirclePnt1.setValue(aStartPnt.pnt()) +aCirclePnt2Ref.setAttr(aEndPnt) +aCirclePnt2.setValue(aEndPnt.pnt()) +aCirclePnt3Ref.setObject(aLine.lastResult()) +aCirclePnt3.setValue(aLineEnd[0], aLineEnd[1]) +aSession.finishOperation() +aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1) +assert aLastFeature == aCircle, "ERROR: SketchMacroCircle has NOT expected to be valid" +aDocument.removeFeature(aCircle) +assert (aSketchFeature.numberOfSubs() == 12) + +#========================================================================= +# Test 5. Create a circle by three points: +# a. first two points are placed on both sides from line +# b. check that this line is not selectable by third point +#========================================================================= +aDistanceFromLine = 20. +aSession.startOperation() +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +aCirclePnt1 = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aCirclePnt2 = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aCirclePnt3 = geomDataAPI_Point2D(aCircle.attribute("third_point")) +aCirclePnt1Ref = aCircle.refattr("first_point_ref") +aCirclePnt2Ref = aCircle.refattr("second_point_ref") +aCirclePnt3Ref = aCircle.refattr("third_point_ref") +aCircleType = aCircle.string("circle_type") +# initialize attributes +aCircleType.setValue("circle_type_by_three_points") +aCirclePnt1.setValue(aLineStart[0] + aDistanceFromLine, aLineStart[1]) +aCirclePnt2.setValue(aLineStart[0] - aDistanceFromLine, aLineStart[1]) +aCirclePnt3Ref.setObject(aLine.lastResult()) +aCirclePnt3.setValue(aLineEnd[0], aLineEnd[1]) +aSession.finishOperation() +aLastFeature = aSketchFeature.subFeature(aSketchFeature.numberOfSubs() - 1) +assert aLastFeature == aCircle, "ERROR: SketchMacroCircle has NOT expected to be valid" +aDocument.removeFeature(aCircle) +assert (aSketchFeature.numberOfSubs() == 12) + +#========================================================================= +# End of test +#========================================================================= + +from salome.shaper import model +assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/Test/TestCreateCircleChangeType.py b/src/SketchPlugin/Test/TestCreateCircleChangeType.py new file mode 100644 index 000000000..92998894a --- /dev/null +++ b/src/SketchPlugin/Test/TestCreateCircleChangeType.py @@ -0,0 +1,171 @@ +""" + TestCreateCircleChangeType.py + + Test attributes reset when changing creation method of a circle on-the-fly +""" + +#========================================================================= +# Initialization of the test +#========================================================================= +from GeomDataAPI import * +from GeomAPI import * +from ModelAPI import * +from SketchAPI import SketchAPI_Sketch +from salome.shaper import model +import math + +__updated__ = "2017-03-22" + + +##========================================================================= +## Auxiliary functions +##========================================================================= + +def assertNotInitializedByCenterAndPassed(theMacroCircle): + # check points + aCenterPoint = geomDataAPI_Point2D(theMacroCircle.attribute("center_point")) + aPassedPoint = geomDataAPI_Point2D(theMacroCircle.attribute("passed_point")) + assert (not aCenterPoint.isInitialized()) + assert (not aPassedPoint.isInitialized()) + # check references + aCenterPointRef = theMacroCircle.refattr("center_point_ref") + aPassedPointRef = theMacroCircle.refattr("passed_point_ref") + assert (not aCenterPointRef.isInitialized()) + assert (not aPassedPointRef.isInitialized()) + +def assertNotInitializedByThreePoints(theMacroCircle): + # check points + aFirstPoint = geomDataAPI_Point2D(theMacroCircle.attribute("first_point")) + aSecondPoint = geomDataAPI_Point2D(theMacroCircle.attribute("second_point")) + aThirdPoint = geomDataAPI_Point2D(theMacroCircle.attribute("third_point")) + assert (not aFirstPoint.isInitialized()) + assert (not aSecondPoint.isInitialized()) + assert (not aThirdPoint.isInitialized()) + # check references + aFirstPointRef = theMacroCircle.refattr("first_point_ref") + aSecondPointRef = theMacroCircle.refattr("second_point_ref") + aThirdPointRef = theMacroCircle.refattr("third_point_ref") + assert (not aFirstPointRef.isInitialized()) + assert (not aSecondPointRef.isInitialized()) + assert (not aThirdPointRef.isInitialized()) + +def distancePointPoint(thePoint1, thePoint2): + return thePoint1.pnt().distance(thePoint2.pnt()) + + +#========================================================================= +# Start of test +#========================================================================= + +aSession = ModelAPI_Session.get() +aDocument = aSession.moduleDocument() +#========================================================================= +# Creation of a sketch +#========================================================================= +aSession.startOperation() +aSketchCommonFeature = aDocument.addFeature("Sketch") +aSketchFeature = featureToCompositeFeature(aSketchCommonFeature) +origin = geomDataAPI_Point(aSketchFeature.attribute("Origin")) +origin.setValue(0, 0, 0) +dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX")) +dirx.setValue(1, 0, 0) +norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm")) +norm.setValue(0, 0, 1) +aSession.finishOperation() +aSketch = SketchAPI_Sketch(aSketchFeature) + +#========================================================================= +# Creation of auxiliary features +#========================================================================= +aSession.startOperation() +aSession.startOperation() +aLine = aSketchFeature.addFeature("SketchLine") +aLineStart = geomDataAPI_Point2D(aLine.attribute("StartPoint")) +aLineStart.setValue(10., 0.) +aLineEnd = geomDataAPI_Point2D(aLine.attribute("EndPoint")) +aLineEnd.setValue(10., 50.) +aSession.finishOperation() + +aSession.startOperation() +#========================================================================= +# Test 1. Create a circle as a macro-feature and check all attributes are not initialized +#========================================================================= +aCircle = aSketchFeature.addFeature("SketchMacroCircle") +assert (aCircle.getKind() == "SketchMacroCircle") +aCenterPoint = geomDataAPI_Point2D(aCircle.attribute("center_point")) +aPassedPoint = geomDataAPI_Point2D(aCircle.attribute("passed_point")) +aFirstPoint = geomDataAPI_Point2D(aCircle.attribute("first_point")) +aSecondPoint = geomDataAPI_Point2D(aCircle.attribute("second_point")) +aThirdPoint = geomDataAPI_Point2D(aCircle.attribute("third_point")) +aCenterPointRef = aCircle.refattr("center_point_ref") +aPassedPointRef = aCircle.refattr("passed_point_ref") +aFirstPointRef = aCircle.refattr("first_point_ref") +aSecondPointRef = aCircle.refattr("second_point_ref") +aThirdPointRef = aCircle.refattr("third_point_ref") +assertNotInitializedByCenterAndPassed(aCircle) +assertNotInitializedByThreePoints(aCircle) +aCircleType = aCircle.string("circle_type") +assert (not aCircleType.isInitialized()) +#========================================================================= +# Test 2. Initialize center of circle, check the three points are not initialized +#========================================================================= +aCircleType.setValue("circle_type_by_center_and_passed_points") +aCenterPoint.setValue(-25., -25.) +assertNotInitializedByThreePoints(aCircle) +#========================================================================= +# Test 3. Change type of circle and check the attributes related to center and passed point became uninitilized +#========================================================================= +aCircleType.setValue("circle_type_by_three_points") +assertNotInitializedByCenterAndPassed(aCircle) +#========================================================================= +# Test 4. Initialize two points and change type, they should became uninitialized +#========================================================================= +aFirstPoint.setValue(-10., 10.) +aSecondPoint.setValue(10., 10.) +aCircleType.setValue("circle_type_by_center_and_passed_points") +assertNotInitializedByThreePoints(aCircle) +#========================================================================= +# Test 5. Initialize center and passed point then change the type +#========================================================================= +aCenterPoint.setValue(-25., -25.) +aPassedPoint.setValue(0., 0.) +aCircleType.setValue("circle_type_by_three_points") +assertNotInitializedByCenterAndPassed(aCircle) +#========================================================================= +# Test 6. Initialize all three points then change the type twice +#========================================================================= +aFirstPoint.setValue(-10., 10.) +aSecondPoint.setValue(10., 10.) +aThirdPoint.setValue(0., 0.) +aCircleType.setValue("circle_type_by_center_and_passed_points") +assertNotInitializedByThreePoints(aCircle) +aCircleType.setValue("circle_type_by_three_points") +assertNotInitializedByCenterAndPassed(aCircle) +#========================================================================= +# Test 7. Initialize first and third points then change the type +#========================================================================= +aFirstPointRef.setAttr(aLineStart) +aFirstPoint.setValue(aLineStart.pnt()) +aThirdPointRef.setObject(aLine.lastResult()) +aThirdPoint.setValue(aLineEnd.pnt()) +aCircleType.setValue("circle_type_by_center_and_passed_points") +assertNotInitializedByThreePoints(aCircle) +#========================================================================= +# Test 8. Initialize center and passed points and finish operation +#========================================================================= +aCenterPointRef.setAttr(aLineStart) +aCenterPoint.setValue(aLineStart.pnt()) +aPassedPointRef.setAttr(aLineEnd) +aPassedPoint.setValue(aLineEnd.pnt()) +aSession.finishOperation() + +aRadius = distancePointPoint(aLineStart, aLineEnd) +assert (aSketchFeature.numberOfSubs() == 2) +verifyLastCircle(aSketchFeature, aLineStart.x(), aLineStart.y(), aRadius) + +#========================================================================= +# End of test +#========================================================================= + +from salome.shaper import model +assert(model.checkPythonDump()) diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index 57c00874a..fa03e34ae 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -97,16 +97,19 @@ icon="icons/Sketch/circle_3pt_32x32.png" title="Three points">