]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Update sketcher unit tests for code coverage
authorazv <azv@opencascade.com>
Mon, 18 Jan 2016 07:55:25 +0000 (10:55 +0300)
committerazv <azv@opencascade.com>
Tue, 19 Jan 2016 11:45:01 +0000 (14:45 +0300)
src/SketchPlugin/Test/TestConstraintConcidence.py
src/SketchPlugin/Test/TestConstraintDistance.py
src/SketchPlugin/Test/TestConstraintEqual.py
src/SketchPlugin/Test/TestConstraintMirror.py
src/SketchPlugin/Test/TestFillet.py
src/SketchPlugin/Test/TestMultiRotation.py
src/SketchPlugin/Test/TestMultiTranslation.py
src/SketchSolver/SketchSolver_ConstraintMulti.cpp
src/SketchSolver/SketchSolver_ConstraintMulti.h
src/SketchSolver/SketchSolver_Group.cpp
src/SketchSolver/SketchSolver_Group.h

index 580a45e3255779ea3e78c8b445990f2345e1237f..81e34ef70677d0cc3f38547135d6178809c517bf 100644 (file)
 """
 from GeomDataAPI import *
 from ModelAPI import *
+import math
 #=========================================================================
 # Initialization of the test
 #=========================================================================
 
 __updated__ = "2014-10-28"
+TOLERANCE = 1.e-7
 
+
+#=========================================================================
+# Auxiliary functions
+#=========================================================================
+def checkPointOnLine(point, line):
+    aStart = geomDataAPI_Point2D(line.attribute("StartPoint"))
+    aEnd   = geomDataAPI_Point2D(line.attribute("EndPoint"))
+    aDirX = aEnd.x() - aStart.x()
+    aDirY = aEnd.y() - aStart.y()
+    aVecX = point.x() - aStart.x()
+    aVecY = point.y() - aStart.y()
+    assert (math.fabs(aDirX * aVecY - aDirY * aVecX) <= TOLERANCE)
+
+def checkPointOnCircle(point, circle):
+    aCenter = geomDataAPI_Point2D(circle.attribute("CircleCenter"))
+    aRadius = circle.real("CircleRadius").value()
+    aDist = math.hypot(point.x() - aCenter.x(), point.y() - aCenter.y())
+    assert (math.fabs(aDist - aRadius) <= TOLERANCE)
+
+def checkPointOnArc(point, arc):
+    aStart  = geomDataAPI_Point2D(arc.attribute("ArcStartPoint"))
+    aCenter = geomDataAPI_Point2D(arc.attribute("ArcCenter"))
+    aRadius = math.hypot(aStart.x() - aCenter.x(), aStart.y() - aCenter.y())
+    aDist = math.hypot(point.x() - aCenter.x(), point.y() - aCenter.y())
+    assert (math.fabs(aDist - aRadius) <= TOLERANCE)
+
+
+#=========================================================================
+# Start of test
+#=========================================================================
 aSession = ModelAPI_Session.get()
 aDocument = aSession.moduleDocument()
+# add an origin
+aSession.startOperation()
+aFeature = aDocument.addFeature("Point")
+aFeature.real("x").setValue(0.)
+aFeature.real("y").setValue(0.)
+aFeature.real("z").setValue(0.)
+anOriginName = aFeature.name()
+aSession.finishOperation()
 #=========================================================================
 # Creation of a sketch
 #=========================================================================
 aSession.startOperation()
-aSketchCommonFeature = aDocument.addFeature("Sketch")
-aSketchFeature = featureToCompositeFeature(aSketchCommonFeature)
+aSketchFeature = featureToCompositeFeature(aDocument.addFeature("Sketch"))
 origin = geomDataAPI_Point(aSketchFeature.attribute("Origin"))
 origin.setValue(0, 0, 0)
 dirx = geomDataAPI_Dir(aSketchFeature.attribute("DirX"))
@@ -79,20 +118,93 @@ assert (aLineStartPoint.y() == 0)
 deltaX = deltaY = 40.
 #  move line
 aSession.startOperation()
-anArcStartPoint.setValue(aLineStartPoint.x() + deltaX,
+aLineStartPoint.setValue(aLineStartPoint.x() + deltaX,
                          aLineStartPoint.y() + deltaY)
-anArcEndPoint.setValue(aLineEndPoint.x() + deltaX,
+aLineEndPoint.setValue(aLineEndPoint.x() + deltaX,
                        aLineEndPoint.y() + deltaY)
 aSession.finishOperation()
 # check that arc's points are moved also
 assert (anArcEndPoint.x() == aLineStartPoint.x())
 assert (anArcEndPoint.y() == aLineStartPoint.y())
 #=========================================================================
-# TODO: improve test
-# 1. remove constraint, move line to check that constraint are not applied
-# 2. make a new constraint when the points are distanced from each other,
-#    check that one from constrainted objects has moved
+# Remove coincidence and move the line
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aConstraint)
+aSession.finishOperation()
+aSession.startOperation()
+aLineStartPoint.setValue(50., 0.)
+aSession.finishOperation()
+assert (anArcEndPoint.x() != aLineStartPoint.x() or anArcEndPoint.y() != aLineStartPoint.y())
+
+#=========================================================================
+# Add constraint point-on-line
+#=========================================================================
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(anArcStartPoint)
+reflistB.setObject(aSketchLine.lastResult())
+aConstraint.execute()
+aSession.finishOperation()
+checkPointOnLine(anArcStartPoint, aSketchLine)
+#=========================================================================
+# Add constraint point-on-circle
+#=========================================================================
+aSession.startOperation()
+# create circle with center coincident with origin
+aSketchCircle = aSketchFeature.addFeature("SketchCircle")
+aCircleCenter = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
+aCircleRadius = aSketchCircle.real("CircleRadius")
+aCircleCenter.setValue(10., 10.)
+aCircleRadius.setValue(25.)
+aSession.finishOperation()
+# create origin
+aSession.startOperation()
+anOrigRes = modelAPI_Result(aDocument.objectByName("Construction", anOriginName))
+assert (anOrigRes)
+anOrigShape = anOrigRes.shape()
+assert (anOrigShape)
+anOrigin = aSketchFeature.addFeature("SketchPoint")
+anOriginCoord = geomDataAPI_Point2D(anOrigin.attribute("PointCoordindates"))
+anOriginCoord.setValue(0., 0.)
+anOrigin.selection("External").setValue(anOrigRes, anOrigShape)
+aSession.finishOperation()
+# coincidence between center of circle and the origin
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(aCircleCenter)
+reflistB.setObject(anOrigin.lastResult())
+aSession.finishOperation()
+# point-on-circle
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setObject(aSketchCircle.lastResult())
+reflistB.setAttr(aLineEndPoint)
+aConstraint.execute()
+aSession.finishOperation()
+checkPointOnCircle(aLineEndPoint, aSketchCircle)
+#=========================================================================
+# Add constraint point-on-arc
+#=========================================================================
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(aCircleCenter)
+reflistB.setObject(aSketchArc.lastResult())
+aConstraint.execute()
+aSession.finishOperation()
+checkPointOnArc(aCircleCenter, aSketchArc)
+#=========================================================================
+# Check center of circle is still in origin
 #=========================================================================
+assert (aCircleCenter.x() == 0. and aCircleCenter.y() == 0.)
 #=========================================================================
 # End of test
 #=========================================================================
index 1e0880e68bbc6d980e8226c2dc433a1a11ef74b8..f1fa087b12ca7f89003731ff9660944572a664bb 100644 (file)
@@ -29,7 +29,7 @@ import math
 __updated__ = "2014-10-28"
 
 
-def distance(pointA, pointB):
+def distancePointPoint(pointA, pointB):
     """
     subroutine to calculate distance between two points
     result of calculated distance is has 10**-5 precision
@@ -38,6 +38,23 @@ def distance(pointA, pointB):
     ydiff = math.pow((pointA.y() - pointB.y()), 2)
     return round(math.sqrt(xdiff + ydiff), 5)
 
+def distancePointLine(point, line):
+    """
+    subroutine to calculate distance between point and line
+    result of calculated distance is has 10**-5 precision
+    """
+    aStartPoint = geomDataAPI_Point2D(line.attribute("StartPoint"))
+    aEndPoint = geomDataAPI_Point2D(line.attribute("EndPoint"))
+    # orthogonal direction
+    aDirX = -(aEndPoint.y() - aStartPoint.y())
+    aDirY = (aEndPoint.x() - aStartPoint.x())
+    aLen = math.sqrt(aDirX**2 + aDirY**2)
+    aDirX = aDirX / aLen
+    aDirY = aDirY / aLen
+    aVecX = point.x() - aStartPoint.x()
+    aVecY = point.y() - aStartPoint.y()
+    return round(math.fabs(aVecX * aDirX + aVecY * aDirY), 5)
+
 aSession = ModelAPI_Session.get()
 aDocument = aSession.moduleDocument()
 #=========================================================================
@@ -70,7 +87,9 @@ aSession.finishOperation()
 #=========================================================================
 # Make a constraint to keep the distance
 #=========================================================================
-assert (distance(aSketchPointCoords, aLineAStartPoint) != 25.)
+PT_PT_DIST = 25.
+aDist = distancePointPoint(aSketchPointCoords, aLineAStartPoint);
+assert (aDist != PT_PT_DIST)
 aSession.startOperation()
 aConstraint = aSketchFeature.addFeature("SketchConstraintDistance")
 aDistance = aConstraint.real("ConstraintValue")
@@ -79,32 +98,70 @@ refattrB = aConstraint.refattr("ConstraintEntityB")
 assert (not aDistance.isInitialized())
 assert (not refattrA.isInitialized())
 assert (not refattrB.isInitialized())
-aDistance.setValue(25.)
 aLineResult = aSketchLine.firstResult()
 assert (aLineResult is not None)
 refattrA.setAttr(aSketchPointCoords)
 refattrB.setAttr(aLineAStartPoint)
 aSession.finishOperation()
-assert (aDistance.isInitialized())
 assert (refattrA.isInitialized())
 assert (refattrB.isInitialized())
+assert (aDistance.isInitialized())
+assert math.fabs(aDistance.value() - aDist) < 1.e-4, "Distance values are different: {0} != {1}".format(aDistance.value(), aDist)
+#=========================================================================
+# Change distance value
+#=========================================================================
+aSession.startOperation()
+aDistance.setValue(PT_PT_DIST)
+aSession.finishOperation()
+assert (distancePointPoint(aSketchPointCoords, aLineAStartPoint) == PT_PT_DIST)
 #=========================================================================
 # Move line, check that distance is constant
 #=========================================================================
-assert (distance(aSketchPointCoords, aLineAStartPoint) == 25.)
 aSession.startOperation()
 aLineAStartPoint.setValue(0., 40.)
 aLineAEndPoint.setValue(100., 40.)
 aSession.finishOperation()
-assert (distance(aSketchPointCoords, aLineAStartPoint) == 25.)
+assert (distancePointPoint(aSketchPointCoords, aLineAStartPoint) == PT_PT_DIST)
 #=========================================================================
-# TODO: improve test
-# 1. remove constraint, move line's start point to
-#    check that constraint are not applied
-# 2. check constrained distance between:
-#    * point and line
-#    * two lines
+# Remove constraint, check the points are unconstrained now
 #=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aConstraint)
+aSession.finishOperation()
+aSession.startOperation()
+aSketchPointCoords.setValue(0., 0.)
+aSession.finishOperation()
+assert (distancePointPoint(aSketchPointCoords, aLineAStartPoint) != PT_PT_DIST)
+
+#=========================================================================
+# Add distance between point and line
+#=========================================================================
+PT_LINE_DIST = 50.
+aDist = distancePointLine(aSketchPointCoords, aSketchLine)
+aSession.startOperation()
+aConstraint = aSketchFeature.addFeature("SketchConstraintDistance")
+aDistance = aConstraint.real("ConstraintValue")
+refattrA = aConstraint.refattr("ConstraintEntityA")
+refattrB = aConstraint.refattr("ConstraintEntityB")
+assert (not aDistance.isInitialized())
+assert (not refattrA.isInitialized())
+assert (not refattrB.isInitialized())
+aLineResult = aSketchLine.firstResult()
+assert (aLineResult is not None)
+refattrA.setObject(aLineResult)
+refattrB.setAttr(aSketchPointCoords)
+aSession.finishOperation()
+assert (refattrA.isInitialized())
+assert (refattrB.isInitialized())
+assert (aDistance.isInitialized())
+assert math.fabs(aDistance.value() - aDist) < 1.e-4, "Distance values are different: {0} != {1}".format(aDistance.value(), aDist)
+#=========================================================================
+# Change distance value
+#=========================================================================
+aSession.startOperation()
+aDistance.setValue(PT_LINE_DIST)
+aSession.finishOperation()
+assert (distancePointLine(aSketchPointCoords, aSketchLine) == PT_LINE_DIST)
 #=========================================================================
 # End of test
 #=========================================================================
index 751be751d52cb044582b19631421e81483301b43..cd3fb37ca6b0f06d08d3526037e8e939a754d135 100644 (file)
@@ -17,9 +17,50 @@ import math
 
 __updated__ = "2015-03-16"
 
+#=========================================================================
+# Auxiliary functions
+#=========================================================================
+def externalSketch(theDoc):
+    aSketchFeature = featureToCompositeFeature(theDoc.addFeature("Sketch"))
+    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)
+    # add circle
+    circle = aSketchFeature.addFeature("SketchCircle")
+    circleCenter = geomDataAPI_Point2D(circle.attribute("CircleCenter"))
+    circleRadius = circle.real("CircleRadius")
+    circleCenter.setValue(-50., 50.)
+    circleRadius.setValue(10.)
+    # add line
+    line = aSketchFeature.addFeature("SketchLine")
+    lineStart = geomDataAPI_Point2D(line.attribute("StartPoint"))
+    lineEnd = geomDataAPI_Point2D(line.attribute("EndPoint"))
+    lineStart.setValue(-40., 35.)
+    lineEnd.setValue(-60., 25.)
+
+def lineLength(theLine):
+    aLineStart = geomDataAPI_Point2D(theLine.attribute("StartPoint"))
+    aLineEnd = geomDataAPI_Point2D(theLine.attribute("EndPoint"))
+    aVecX = aLineStart.x() - aLineEnd.x()
+    aVecY = aLineStart.y() - aLineEnd.y()
+    return math.hypot(aVecX, aVecY)
+
+
+#=========================================================================
+# Start of test
+#=========================================================================
 aSession = ModelAPI_Session.get()
 aDocument = aSession.moduleDocument()
 #=========================================================================
+# Creation external sketch
+#=========================================================================
+aSession.startOperation()
+externalSketch(aDocument)
+aSession.finishOperation()
+#=========================================================================
 # Creation of a sketch
 #=========================================================================
 aSession.startOperation()
@@ -49,7 +90,7 @@ aSession.startOperation()
 aSketchCircle = aSketchFeature.addFeature("SketchCircle")
 anCircleCentr = geomDataAPI_Point2D(aSketchCircle.attribute("CircleCenter"))
 aCircleRadius = aSketchCircle.real("CircleRadius")
-anCircleCentr.setValue(-25., -25)
+anCircleCentr.setValue(-25., -25.)
 aCircleRadius.setValue(25.)
 aSession.finishOperation()
 #=========================================================================
@@ -68,10 +109,38 @@ aRefObjectB.setObject(aResultB)
 aConstraintEqRad.execute()
 aSession.finishOperation()
 aCircRadius = aCircleRadius.value();
-anArcVecX = anArcStartPoint.x() - anArcCentr.x();
-anArcVecY = anArcStartPoint.y() - anArcCentr.y();
+anArcVecX = anArcStartPoint.x() - anArcCentr.x()
+anArcVecY = anArcStartPoint.y() - anArcCentr.y()
 anArcRadius = math.sqrt(anArcVecX**2 + anArcVecY**2)
 assert (math.fabs(aCircRadius - anArcRadius) <= 1.e-10)
+#=========================================================================
+# A constraint to make equal radii of arc and external circle
+#=========================================================================
+aSession.startOperation()
+anExtCircRes = modelAPI_Result(aDocument.objectByName("Construction", "SketchCircle_1"))
+assert(anExtCircRes)
+anExtCircShape = anExtCircRes.shape()
+assert(anExtCircShape)
+anExtCircle = aSketchFeature.addFeature("SketchCircle")
+anExtCircleCenter = geomDataAPI_Point2D(anExtCircle.attribute("CircleCenter"))
+anExtCircleRadius = anExtCircle.real("CircleRadius")
+anExtCircleCenter.setValue(-50., 50.)
+anExtCircleRadius.setValue(10.)
+anExtCircle.selection("External").setValue(anExtCircRes, anExtCircShape)
+aSession.finishOperation()
+aSession.startOperation()
+aConstraintEqRad2 = aSketchFeature.addFeature("SketchConstraintEqual")
+aRefObjectA = aConstraintEqRad2.refattr("ConstraintEntityA")
+aRefObjectB = aConstraintEqRad2.refattr("ConstraintEntityB")
+aRefObjectA.setObject(aSketchCircle.lastResult())
+aRefObjectB.setObject(anExtCircle.lastResult())
+aSession.finishOperation()
+assert (math.fabs(anExtCircleRadius.value() - aCircleRadius.value()) < 1.e-10)
+anArcVecX = anArcStartPoint.x() - anArcCentr.x()
+anArcVecY = anArcStartPoint.y() - anArcCentr.y()
+anArcRadius = math.sqrt(anArcVecX**2 + anArcVecY**2)
+assert (math.fabs(anExtCircleRadius.value() - anArcRadius) <= 1.e-10)
+
 #=========================================================================
 # Creation of two different lines
 #=========================================================================
@@ -106,13 +175,36 @@ aRefObjectA.setObject(aResultA)
 aRefObjectB.setObject(aResultB)
 aConstraintEqLen.execute()
 aSession.finishOperation()
-aVecX = aLine1StartPoint.x() - aLine1EndPoint.x();
-aVecY = aLine1StartPoint.y() - aLine1EndPoint.y();
-aLine1Len = math.sqrt(anArcVecX * anArcVecX + anArcVecY * anArcVecY)
-aVecX = aLine2StartPoint.x() - aLine2EndPoint.x();
-aVecY = aLine2StartPoint.y() - aLine2EndPoint.y();
-aLine2Len = math.sqrt(anArcVecX**2 + anArcVecY**2)
-assert (aLine1Len == aLine2Len)
+aLine1Len = lineLength(aSketchLine1)
+aLine2Len = lineLength(aSketchLine2)
+assert (math.fabs(aLine1Len - aLine2Len) < 1.e-10)
+#=========================================================================
+# A constraint to make equal length of line with external line
+#=========================================================================
+aSession.startOperation()
+anExtLineRes = modelAPI_Result(aDocument.objectByName("Construction", "SketchLine_1"))
+assert(anExtLineRes)
+anExtLineShape = anExtLineRes.shape()
+assert(anExtLineShape)
+anExtLine = aSketchFeature.addFeature("SketchLine")
+anExtLineStart = geomDataAPI_Point2D(anExtLine.attribute("StartPoint"))
+anExtLineEnd = geomDataAPI_Point2D(anExtLine.attribute("EndPoint"))
+anExtLineStart.setValue(-40., 35.)
+anExtLineEnd.setValue(-60., 25.)
+anExtLine.selection("External").setValue(anExtLineRes, anExtLineShape)
+anExtLineLen = lineLength(anExtLine)
+aSession.finishOperation()
+aSession.startOperation()
+aConstraintEqLen2 = aSketchFeature.addFeature("SketchConstraintEqual")
+aRefObjectA = aConstraintEqLen2.refattr("ConstraintEntityA")
+aRefObjectB = aConstraintEqLen2.refattr("ConstraintEntityB")
+aRefObjectA.setObject(anExtLine.lastResult())
+aRefObjectB.setObject(aSketchLine2.lastResult())
+aSession.finishOperation()
+aLine1Len = lineLength(aSketchLine1)
+aLine2Len = lineLength(aSketchLine2)
+assert (math.fabs(aLine1Len - anExtLineLen) < 1.e-10)
+assert (math.fabs(aLine2Len - anExtLineLen) < 1.e-10)
 #=========================================================================
 # End of test
 #=========================================================================
index 43d2c45bb3fc2a1c32010e6c692219b7ecc7718d..6c36789708f6f781bcaa7a1e207640dfda02ccd4 100644 (file)
@@ -18,6 +18,46 @@ import math
 
 __updated__ = "2015-03-17"
 
+#=========================================================================
+# Auxiliary functions
+#=========================================================================
+def checkMirror(theListInit, theListMirr, theMirrorLine):
+    aListSize = theListInit.size()
+    
+    aLineStartPoint = geomDataAPI_Point2D(theMirrorLine.attribute("StartPoint"))
+    aLineEndPoint = geomDataAPI_Point2D(theMirrorLine.attribute("EndPoint"))
+    aLineDirX = aLineEndPoint.x() - aLineStartPoint.x()
+    aLineDirY = aLineEndPoint.y() - aLineStartPoint.y()
+
+    for ind in range(0, aListSize):
+        aFeatureB = ModelAPI_Feature.feature(theListInit.object(ind))
+        aFeatureC = ModelAPI_Feature.feature(theListMirr.object(ind))
+        assert(aFeatureB is not None)
+        assert(aFeatureC is not None)
+        assert(aFeatureB.getKind() == aFeatureC.getKind())
+        
+        anAttributes = {}
+        if (aFeatureB.getKind() == "SketchLine"):
+            anAttributes = {'StartPoint':'StartPoint', 'EndPoint':'EndPoint'}
+        elif (aFeatureB.getKind() == "SketchArc"):
+            anAttributes = {'ArcCenter':'ArcCenter', 'ArcStartPoint':'ArcEndPoint', 'ArcEndPoint':'ArcStartPoint'}
+        
+        for key in anAttributes:
+            aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
+            aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key]))
+            aDirX = aPointC.x() - aPointB.x()
+            aDirY = aPointC.y() - aPointB.y()
+            aDot = aLineDirX * aDirX + aLineDirY * aDirY
+            assert(math.fabs(aDot) < 1.e-10)
+            aDirX = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x())
+            aDirY = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y())
+            aCross = aLineDirX * aDirY - aLineDirY * aDirX
+            assert(math.fabs(aCross) < 1.e-10)
+
+
+#=========================================================================
+# Start of test
+#=========================================================================
 aSession = ModelAPI_Session.get()
 aDocument = aSession.moduleDocument()
 #=========================================================================
@@ -113,44 +153,44 @@ aSession.startOperation()
 aMirror = aSketchFeature.addFeature("SketchConstraintMirror")
 aRefObjectA = aMirror.refattr("ConstraintEntityA")
 aRefObjectA.setObject(modelAPI_ResultConstruction(aMirrorLine.firstResult()))
-aRefListB = aMirror.reflist("ConstraintEntityB")
-aRefListB.append(aSketchArc1)
-aRefListB.append(aSketchLine1)
-aRefListB.append(aSketchLine2)
+aRefListInitial = aMirror.reflist("ConstraintMirrorList")
+aRefListInitial.append(aSketchArc1.lastResult())
+aRefListInitial.append(aSketchLine1.lastResult())
+aRefListInitial.append(aSketchLine2.lastResult())
 aMirror.execute()
 aSession.finishOperation()
 #=========================================================================
 # Verify the simmetricity of all mirrored objects
 #=========================================================================
+aRefListB = aMirror.reflist("ConstraintEntityB")
 aRefListC = aMirror.reflist("ConstraintEntityC")
-aListSize = aRefListB.size()
-aLineDirX = aLineEndPoint.x() - aLineStartPoint.x()
-aLineDirY = aLineEndPoint.y() - aLineStartPoint.y()
+assert (aRefListB.size() == 3)
+assert (aRefListC.size() == 3)
+checkMirror(aRefListB, aRefListC, aMirrorLine)
 
-for ind in range(0, aListSize):
-  aFeatureB = modelAPI_Feature(aRefListB.object(ind))
-  aFeatureC = modelAPI_Feature(aRefListC.object(ind))
-  assert(aFeatureB is not None)
-  assert(aFeatureC is not None)
-  assert(aFeatureB.getKind() == aFeatureC.getKind())
-  anAttributes = {}
-  print aFeatureB.getKind()
-  if (aFeatureB.getKind() == "SketchLine"):
-    anAttributes = {'StartPoint':'StartPoint', 'EndPoint':'EndPoint'}
-  elif (aFeatureB.getKind() == "SketchArc"):
-    anAttributes = {'ArcCenter':'ArcCenter', 'ArcStartPoint':'ArcEndPoint', 'ArcEndPoint':'ArcStartPoint'}
+#=========================================================================
+# Remove object from mirror
+#=========================================================================
+aSession.startOperation()
+aRefListInitial.remove(aSketchLine2.lastResult())
+aSession.finishOperation()
+assert (aRefListB.size() == 2)
+assert (aRefListC.size() == 2)
+checkMirror(aRefListB, aRefListC, aMirrorLine)
 
-  for key in anAttributes:
-    aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
-    aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key]))
-    aDirX = aPointC.x() - aPointB.x()
-    aDirY = aPointC.y() - aPointB.y()
-    aDot = aLineDirX * aDirX + aLineDirY * aDirY
-    assert(math.fabs(aDot) < 1.e-10)
-    aDirX = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x())
-    aDirY = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y())
-    aCross = aLineDirX * aDirY - aLineDirY * aDirX
-    assert(math.fabs(aCross) < 1.e-10)
+#=========================================================================
+# Clear list of mirrored features
+#=========================================================================
+aSession.startOperation()
+aRefListInitial.clear()
+assert (aRefListB.size() == 0)
+assert (aRefListC.size() == 0)
+# add arc once again
+aRefListInitial.append(aSketchArc1.lastResult())
+aSession.finishOperation()
+assert (aRefListB.size() == 1)
+assert (aRefListC.size() == 1)
+checkMirror(aRefListB, aRefListC, aMirrorLine)
 #=========================================================================
 # End of test
 #=========================================================================
index 72bf010ebea4f50d8865e2a63c0a16246a131a32..b4f648693aa91d41dfc2074dcd996d07f9e77b77 100644 (file)
@@ -19,7 +19,7 @@ import math
 #=========================================================================
 aStartPoint1 = []
 
-def createSketch(theSketch):
+def createSketch1(theSketch):
     global aStartPoint1
     # Initialize sketch by two lines with coincident boundary
     allFeatures = []
@@ -44,9 +44,39 @@ def createSketch(theSketch):
     
     theSketch.execute()
     return allFeatures
+
+
+def createSketch2(theSketch):
+    global aStartPoint1
+    # Initialize sketch by line and arc with coincident boundary
+    allFeatures = []
+    # Line
+    aSketchLine = theSketch.addFeature("SketchLine")
+    aStartPoint1 = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
+    aEndPoint1   = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint"))
+    aStartPoint1.setValue(10., 10.)
+    aEndPoint1.setValue(30., 5.)
+    allFeatures.append(aSketchLine)
+    # Arc
+    aSketchArc = theSketch.addFeature("SketchArc")
+    aStartPoint2 = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
+    aEndPoint2   = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
+    aCenterPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
+    aCenterPoint.setValue(20., 10.)
+    aStartPoint2.setValue(10., 10.)
+    aEndPoint2.setValue(20., 0.)
+    allFeatures.append(aSketchArc)
+    # Coincidence
+    aCoincidence = theSketch.addFeature("SketchConstraintCoincidence")
+    aCoincidence.refattr("ConstraintEntityA").setAttr(aStartPoint1)
+    aCoincidence.refattr("ConstraintEntityB").setAttr(aStartPoint2)
+    
+    theSketch.execute()
+    return allFeatures
     
 def checkFillet(theObjects, theRadius):
     # Verify the arc and lines are connected smoothly
+    print "Check Fillet"
     aLine = []
     anArc = []
     aSize = theObjects.size()
@@ -57,20 +87,22 @@ def checkFillet(theObjects, theRadius):
             aLine.append(feat)
         elif (feat.getKind() == "SketchArc"):
             anArc.append(feat)
-    assert(anArc)
-    assert(anArc[0] is not None)
+    aFilletArc = anArc[-1]
+    assert(aFilletArc is not None)
+    anArc.pop()
     
     anArcPoints = []
-    aPoint = geomDataAPI_Point2D(anArc[0].attribute("ArcStartPoint"))
+    aPoint = geomDataAPI_Point2D(aFilletArc.attribute("ArcStartPoint"))
     print "ArcStartPoint " + repr(aPoint.x()) + " " + repr(aPoint.y())
     anArcPoints.append((aPoint.x(), aPoint.y()))
-    aPoint = geomDataAPI_Point2D(anArc[0].attribute("ArcEndPoint"))
+    aPoint = geomDataAPI_Point2D(aFilletArc.attribute("ArcEndPoint"))
     print "ArcEndPoint " + repr(aPoint.x()) + " " + repr(aPoint.y())
     anArcPoints.append((aPoint.x(), aPoint.y()))
-    aPoint = geomDataAPI_Point2D(anArc[0].attribute("ArcCenter"))
+    aPoint = geomDataAPI_Point2D(aFilletArc.attribute("ArcCenter"))
     print "ArcCenter " + repr(aPoint.x()) + " " + repr(aPoint.y())
     aCenterX = aPoint.x()
     aCenterY = aPoint.y()
+    aFilletRadius = math.hypot(anArcPoints[0][0]-aCenterX, anArcPoints[0][1]-aCenterY)
     
     for line in aLine:
         aStartPoint = geomDataAPI_Point2D(line.attribute("StartPoint"))
@@ -95,6 +127,22 @@ def checkFillet(theObjects, theRadius):
                     
                     break;
 
+    for arc in anArc:
+        aStartPoint = geomDataAPI_Point2D(arc.attribute("ArcStartPoint"))
+        aEndPoint = geomDataAPI_Point2D(arc.attribute("ArcEndPoint"))
+        aCenterPoint = geomDataAPI_Point2D(arc.attribute("ArcCenter"))
+        
+        aBaseArcPoints = []
+        aBaseArcPoints.append((aStartPoint.x(), aStartPoint.y()))
+        print "anArcStartPoint " + repr(aStartPoint.x()) + " " + repr(aStartPoint.y())
+        aBaseArcPoints.append((aEndPoint.x(), aEndPoint.y()))
+        print "anArcEndPoint " + repr(aEndPoint.x()) + " " + repr(aEndPoint.y())
+        print "anArcCenter " + repr(aCenterPoint.x()) + " " + repr(aCenterPoint.y())
+        
+        aRadius = math.hypot(aStartPoint.x()-aCenterPoint.x(), aStartPoint.y()-aCenterPoint.y())
+        aDist = math.hypot(aCenterPoint.x() - aCenterX, aCenterPoint.y() - aCenterY)
+        assert math.fabs(aFilletRadius + aRadius - aDist) < 1.e-7 or math.fabs(math.fabs(aFilletRadius - aRadius) - aDist) < 1.e-7, \
+            "Fillet radius = {0}, Base arc radius = {1}, distance between centers = {2}".format(aFilletRadius, aRadius, aDist)
 
 
 #=========================================================================
@@ -119,10 +167,10 @@ norm = geomDataAPI_Dir(aSketchFeature.attribute("Norm"))
 norm.setValue(0, 0, 1)
 aSession.finishOperation()
 #=========================================================================
-# Initialize sketch
+# Initialize sketch by two lines
 #=========================================================================
 aSession.startOperation()
-aFeaturesList = createSketch(aSketchFeature)
+aFeaturesList = createSketch1(aSketchFeature)
 aSession.finishOperation()
 #=========================================================================
 # Global variables
@@ -146,8 +194,55 @@ aResObjects = aFillet.reflist("ConstraintEntityB")
 # Verify the objects of fillet are created
 #=========================================================================
 assert(aResObjects)
+checkFillet(aResObjects, FILLET_RADIUS1)
+#=========================================================================
+# Change Fillet radius
+#=========================================================================
+aRadius.setValue(FILLET_RADIUS2)
+aSession.finishOperation()
+checkFillet(aResObjects, FILLET_RADIUS2)
+
+#=========================================================================
+# Create another 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, 1, 0)
+aSession.finishOperation()
+#=========================================================================
+# Initialize sketch by line and arc
+#=========================================================================
+aSession.startOperation()
+aFeaturesList = createSketch2(aSketchFeature)
 aSession.finishOperation()
+#=========================================================================
+# Create the Fillet
+#=========================================================================
+aSession.startOperation()
+aFillet = aSketchFeature.addFeature("SketchConstraintFillet")
+aRefAttrA = aFillet.refattr("ConstraintEntityA");
+aRefAttrA.setAttr(aStartPoint1)
+aRadius = aFillet.real("ConstraintValue")
+aRadius.setValue(FILLET_RADIUS1)
+aFillet.execute()
+aResObjects = aFillet.reflist("ConstraintEntityB")
+#=========================================================================
+# Verify the objects of fillet are created
+#=========================================================================
+assert(aResObjects)
 checkFillet(aResObjects, FILLET_RADIUS1)
 #=========================================================================
+# Change Fillet radius
+#=========================================================================
+aRadius.setValue(FILLET_RADIUS2)
+aSession.finishOperation()
+checkFillet(aResObjects, FILLET_RADIUS2)
+#=========================================================================
 # End of test
 #=========================================================================
index 34cb0387f29851d687656c5aceca99e33de33062..27b0aae2430b8fc0de718f988352bc18884a4e64 100644 (file)
@@ -35,6 +35,15 @@ def createSketch(theSketch):
     theSketch.execute()
     return allFeatures
     
+def createLine(theSketch):
+    aSketchLine = theSketch.addFeature("SketchLine")
+    aStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
+    aEndPoint   = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint"))
+    aStartPoint.setValue(7., 5.)
+    aEndPoint.setValue(1., 3.)
+    theSketch.execute()
+    return aSketchLine
+    
 def checkRotation(theObjects, theNbObjects, theCenterX, theCenterY, theAngle):
     # Verify distances of the objects and the number of copies
     aFeatures = []
@@ -159,11 +168,54 @@ aNbCopies.setValue(3)
 aSession.finishOperation()
 aRotated = aMultiRotation.reflist("ConstraintEntityB")
 checkRotation(aRotated, aNbCopies.value(), CENTER_X, CENTER_Y, ANGLE)
+
+#=========================================================================
+# Create new feature and add it into the Rotation
+#=========================================================================
+aSession.startOperation()
+aLine = createLine(aSketchFeature)
+aSession.finishOperation()
+aSession.startOperation()
+aResult = modelAPI_ResultConstruction(aLine.lastResult())
+assert(aResult is not None)
+aRotList.append(aResult)
+aSession.finishOperation()
+checkRotation(aRotated, aNbCopies.value(), CENTER_X, CENTER_Y, ANGLE)
+#=========================================================================
+# Move line and check the copies are moved too
+#=========================================================================
+aSession.startOperation()
+aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+aStartPoint.setValue(12., 5.)
+aSession.finishOperation()
+checkRotation(aRotated, aNbCopies.value(), CENTER_X, CENTER_Y, ANGLE)
+#=========================================================================
+# Change number of copies and verify Rotation
+#=========================================================================
+aSession.startOperation()
+aNbCopies.setValue(2)
+aSession.finishOperation()
+checkRotation(aRotated, aNbCopies.value(), CENTER_X, CENTER_Y, ANGLE)
+
+#=========================================================================
+# Remove a feature from the Rotation
+#=========================================================================
+aSession.startOperation()
+aRemoveIt = aRotList.object(0)
+aRotList.remove(aRemoveIt)
+aSession.finishOperation()
+checkRotation(aRotated, aNbCopies.value(), CENTER_X, CENTER_Y, ANGLE)
+
 #=========================================================================
-# TODO: improve test
-# 1. Add more features into Rotation
-# 2. Move one of initial features and check the Rotated is moved too
+# Clear the list of rotated features
 #=========================================================================
+aSession.startOperation()
+aRotList.clear()
+checkRotation(aRotated, 1, CENTER_X, CENTER_Y, ANGLE)
+# Add line once again
+aRotList.append(aResult)
+aSession.finishOperation()
+checkRotation(aRotated, aNbCopies.value(), CENTER_X, CENTER_Y, ANGLE)
 #=========================================================================
 # End of test
 #=========================================================================
index 4dca56c495ccc26fd4b5712f59209024197192a5..2c0a2b9373ed2c93a83e469f8345a0d7302517da 100644 (file)
@@ -34,6 +34,15 @@ def createSketch(theSketch):
     theSketch.execute()
     return allFeatures
     
+def createLine(theSketch):
+    aSketchLine = theSketch.addFeature("SketchLine")
+    aStartPoint = geomDataAPI_Point2D(aSketchLine.attribute("StartPoint"))
+    aEndPoint   = geomDataAPI_Point2D(aSketchLine.attribute("EndPoint"))
+    aStartPoint.setValue(7., 5.)
+    aEndPoint.setValue(1., 3.)
+    theSketch.execute()
+    return aSketchLine
+    
 def checkTranslation(theObjects, theNbObjects, theDeltaX, theDeltaY):
     # Verify distances of the objects and the number of copies
     aFeatures = []
@@ -46,7 +55,7 @@ def checkTranslation(theObjects, theNbObjects, theDeltaX, theDeltaY):
     anInd = 0 
     for feat, next in zip(aFeatures[:-1], aFeatures[1:]):
         anInd = anInd + 1
-        if (anInd > theNbObjects):
+        if (anInd > theNbObjects-1):
             anInd = 0
             continue
         assert(feat.getKind() == next.getKind())
@@ -150,11 +159,54 @@ aNbCopies.setValue(3)
 aSession.finishOperation()
 aTranslated = aMultiTranslation.reflist("ConstraintEntityB")
 checkTranslation(aTranslated, aNbCopies.value(), DELTA_X, DELTA_Y)
+
+#=========================================================================
+# Create new feature and add it into the Rotation
+#=========================================================================
+aSession.startOperation()
+aLine = createLine(aSketchFeature)
+aSession.finishOperation()
+aSession.startOperation()
+aResult = modelAPI_ResultConstruction(aLine.lastResult())
+assert(aResult is not None)
+aTransList.append(aResult)
+aSession.finishOperation()
+checkTranslation(aTranslated, aNbCopies.value(), DELTA_X, DELTA_Y)
+#=========================================================================
+# Move line and check the copies are moved too
+#=========================================================================
+aSession.startOperation()
+aStartPoint = geomDataAPI_Point2D(aLine.attribute("StartPoint"))
+aStartPoint.setValue(12., 5.)
+aSession.finishOperation()
+checkTranslation(aTranslated, aNbCopies.value(), DELTA_X, DELTA_Y)
 #=========================================================================
-# TODO: improve test
-# 1. Add more features into translation
-# 2. Move one of initial features and check the translated is moved too
+# Change number of copies and verify Rotation
 #=========================================================================
+aSession.startOperation()
+aNbCopies.setValue(2)
+aSession.finishOperation()
+checkTranslation(aTranslated, aNbCopies.value(), DELTA_X, DELTA_Y)
+
+#=========================================================================
+# Remove a feature from the Rotation
+#=========================================================================
+aSession.startOperation()
+aRemoveIt = aTransList.object(0)
+aTransList.remove(aRemoveIt)
+aSession.finishOperation()
+checkTranslation(aTranslated, aNbCopies.value(), DELTA_X, DELTA_Y)
+
+#=========================================================================
+# Clear the list of rotated features
+#=========================================================================
+aSession.startOperation()
+aTransList.clear()
+checkTranslation(aTranslated, 1, DELTA_X, DELTA_Y)
+# Add line once again
+aTransList.append(aResult)
+aSession.finishOperation()
+checkTranslation(aTranslated, aNbCopies.value(), DELTA_X, DELTA_Y)
 #=========================================================================
 # End of test
 #=========================================================================
index d2135179c35538fe52fe63c8f0c779218fafa86e..96fa9ea2f8f3e2ab7eebc2feb1a2c33f3680aaf0 100644 (file)
@@ -42,24 +42,53 @@ void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theE
 
     myStorage->update(aFeature);
     theEntities.push_back(myStorage->entity(aFeature));
-    for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt)
-      ; // just skip copied features
+    myFeatures.insert(aFeature);
+    for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
+      // just add copied features into the list of objects
+      aFeature = ModelAPI_Feature::feature(*anObjIt);
+      if (aFeature)
+        myFeatures.insert(aFeature);
+    }
   }
 }
 
+bool SketchSolver_ConstraintMulti::remove()
+{
+  myFeatures.clear();
+  return SketchSolver_Constraint::remove();
+}
+
 void SketchSolver_ConstraintMulti::update()
 {
   update(false);
 }
 
-
 void SketchSolver_ConstraintMulti::update(bool isForce)
 {
   cleanErrorMsg();
   AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
       myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
   AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
-  if (anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies) {
+  bool isUpdated= anInitialRefList->size() != myNumberOfObjects || aNbObjects->value()-1 != myNumberOfCopies;
+  if (!isUpdated) {
+    // additional check that the features and their copies are changed
+    AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+        myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+    if (aRefList && aRefList->size() != 0) {
+      FeaturePtr aFeature;
+      std::list<ObjectPtr> anObjectList = aRefList->list();
+      std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
+      for (; anObjIt != anObjectList.end(); ++anObjIt) {
+        aFeature = ModelAPI_Feature::feature(*anObjIt);
+        if (aFeature && myFeatures.find(aFeature) == myFeatures.end()) {
+          isUpdated = true;
+          break;
+        }
+      }
+    } else
+      isUpdated = true;
+  }
+  if (isUpdated) {
     remove();
     process();
     return;
index 16db54dbde8881cb2178a782c4515850705d8621..03f0a69235a546db0358e4fb3d7ab546973778aa 100644 (file)
@@ -32,6 +32,10 @@ public:
   /// \brief Update constraint
   void update(bool isForce);
 
+  /// \brief Tries to remove constraint
+  /// \return \c false, if current constraint contains another SketchPlugin constraints (like for multiple coincidence)
+  virtual bool remove();
+
 protected:
   /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
   virtual void process()
@@ -68,6 +72,8 @@ protected:
   int myNumberOfCopies;  ///< number of previous copies of initial objects
 
   bool myAdjusted; ///< the constraint is already adjusted (to not do it several times)
+
+  std::set<FeaturePtr> myFeatures; ///< list of features and their copies to find whether some of them are disappeared
 };
 
 #endif
index 7ef43366f6655847175729af79ad06ddfeaf37e7..c74580b07a479099cbdb40dfe0bac6cada2ca8bb 100644 (file)
@@ -172,30 +172,6 @@ bool SketchSolver_Group::changeConstraint(
   return true;
 }
 
-
-void SketchSolver_Group::updateConstraints()
-{
-  std::set<SolverConstraintPtr> aPostponed; // postponed constraints Multi-Rotation and Multi-Translation
-
-  ConstraintConstraintMap::iterator anIt = myConstraints.begin();
-  for (; anIt != myConstraints.end(); ++anIt) {
-    if (myChangedConstraints.find(anIt->first) == myChangedConstraints.end())
-      continue;
-    if (anIt->first->getKind() == SketchPlugin_MultiRotation::ID() ||
-        anIt->first->getKind() == SketchPlugin_MultiTranslation::ID())
-      aPostponed.insert(anIt->second);
-    else
-      anIt->second->update();
-  }
-
-  // Update postponed constraints
-  std::set<SolverConstraintPtr>::iterator aSCIter = aPostponed.begin();
-  for (; aSCIter != aPostponed.end(); ++aSCIter)
-    (*aSCIter)->update();
-
-  myChangedConstraints.clear();
-}
-
 static void updateMultiConstraints(ConstraintConstraintMap& theConstraints, FeaturePtr theFeature)
 {
   ConstraintConstraintMap::iterator aCIt = theConstraints.begin();
@@ -293,9 +269,6 @@ bool SketchSolver_Group::updateWorkplane()
 // ============================================================================
 bool SketchSolver_Group::resolveConstraints()
 {
-  if (!myChangedConstraints.empty())
-    updateConstraints();
-
   bool aResolved = false;
   bool isGroupEmpty = isEmpty();
   if (myStorage->isNeedToResolve() && !isGroupEmpty) {
index f1520d3bd94b47099f4769facd16fded4bb060b4..7544fbaa2c7600d32348054ea90f37449e15ea96 100644 (file)
@@ -152,9 +152,6 @@ private:
   /// \brief Verifies is the feature valid
   bool checkFeatureValidity(FeaturePtr theFeature);
 
-  /// \brief Update just changed constraints
-  void updateConstraints();
-
 private:
   GroupID  myID; ///< Index of the group
   EntityID myWorkplaneID; ///< Index of workplane, the group is based on
@@ -162,7 +159,6 @@ private:
   ConstraintConstraintMap myConstraints; ///< List of constraints
   std::set<SolverConstraintPtr> myTempConstraints; ///< List of temporary constraints
   std::map<AttributePtr, SolverConstraintPtr> myParametricConstraints; ///< List of parametric constraints
-  std::set<ConstraintPtr> myChangedConstraints; ///< List of just updated constraints
 
   StoragePtr myStorage; ///< Container for the set of SolveSpace constraints and their entities