* Improve SketchSolver_Manager to add features placed in a single sketch into a single group
* Remove unnecessary IDs for entities and parameters. Do not set GroupID for such kind of elements.
* Remove unnecessary IDs for groups
* Check feature validity on at the very beginning of processing.
* Fix problems when deleting temporary constraint built for correct restart of an operation.
* Remove data structure to store lists of coincident points.
* Integrate SketchSolver sources into PlaneGCSSolver plugin
* Take out ParameterWrapper
* Move converting and removing entities to specific classes
* Remove notifications on changing point-point coincidences.
* Update processing Fixed constraint (make it more natural to PlaneGCS). Remove Movement constraint as unneeded.
* Repair Point-point coincidence and the Fixed constraints
* Fix incorrect processing of the Update event.
* Repair Point-on-Line and Point-on-Circle constraints.
* Repair processing of external features
* Processing of point-point multi-coincidence has been updated. Unit test has been improved.
* Repair constraints: Horizontal, Vertical, Parallel, Perpendicular, Radius, Distance, Length, Equal and Tangent
* Fix issue that arc cannot be created on the sketch with constraints
* Repair Angle and Middle point constraints.
* Repair Multi-Rotation and Multi-Translation constraints.
* Introduce Updaters to send changed features to interested object only.
* Remove the Fixed constraint applying on the external features.
* Update Multi-* constraints to use Updaters.
* Mirror constraint redesign
* Remove obsolete std::dynamic_pointer_cast
* Optimize blocking events while solving constraints
* Update Coincidence and Middle Point constraints processing (move checking multi coincidence to the constraint layer)
//if (!theTemporary) {
aMyFeature->execute();
- // fix this edge
- FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
- aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
- setObject(aMyFeature->lastResult());
- // we need to flush created signal in order to fixed constraint is processed by solver
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+ // // fix this edge
+ // FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
+ // aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
+ // setObject(aMyFeature->lastResult());
+ // // we need to flush created signal in order to fixed constraint is processed by solver
+ // Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
//}
return aMyFeature->lastResult();
}
//if (theTemporary) {
aMyFeature->execute();
- // fix this edge
- FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
- aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
- setObject(aMyFeature->lastResult());
- // we need to flush created signal in order to fixed constraint is processed by solver
- Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
+ // // fix this edge
+ // FeaturePtr aFix = theSketch->addFeature(SketchPlugin_ConstraintRigid::ID());
+ // aFix->data()->refattr(SketchPlugin_Constraint::ENTITY_A())->
+ // setObject(aMyFeature->lastResult());
+ // // we need to flush created signal in order to fixed constraint is processed by solver
+ // Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
//}
return aMyFeature->lastResult();
}
# Set the constraint
circle_1 = self.sketch.addCircle(0, 0, 10.0)
circle_2 = self.sketch.addCircle(1, 2, 25.0)
- self.sketch.setEqual(circle_1.result(), circle_2.result())
+ self.sketch.setEqual(circle_1.defaultResult(), circle_2.defaultResult())
# Commit the transaction
model.do()
# Check the result
self.assertAlmostEqual(
- circle_1.radiusData().value(),
- circle_2.radiusData().value(),
+ circle_1.radius().value(),
+ circle_2.radius().value(),
delta=TestSketcher.DELTA
)
# Creating a cylinder on a face of the box
thisface = "Extrusion_1_1/Generated_Face_2"
-thisxmax = "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2"
+thisxmax = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"
thiszmax = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1_1"
mystand = model.addSketch(mypart, thisface)
# Creating a cylinder on a face of the box
thisface = "Extrusion_1_1/Generated_Face_2"
-thisxmin = "Extrusion_1_1/Generated_Face_3&Extrusion_1_1/Generated_Face_2"
+thisxmin = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/Generated_Face_1"
thiszmax = "Extrusion_1_1/Generated_Face_2&Extrusion_1_1/To_Face_1_1"
mystand = model.addSketch(mypart, thisface)
TestHighload.py
TestSnowflake.py
TestArcBehavior.py
+ Test1061.py
Test1924.py )
{
if (!sketch())
return thePrevious;
-
- AISObjectPtr anAIS = thePrevious;
-
- bool isValidRigid = false;
- std::shared_ptr<ModelAPI_Data> aData = data();
- AttributeRefAttrPtr anAttr = aData->refattr(SketchPlugin_Constraint::ENTITY_A());
- ObjectPtr aObj = anAttr->object();
- if (aObj.get() != NULL) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
- std::shared_ptr<SketchPlugin_Feature> aSkFea =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (!aSkFea->isExternal())
- isValidRigid = true;
- }
-
- if (isValidRigid)
- anAIS = SketcherPrs_Factory::rigidConstraint(this, sketch()->coordinatePlane(), thePrevious);
- else
- anAIS = AISObjectPtr();
-
- return anAIS;
+ return SketcherPrs_Factory::rigidConstraint(this, sketch()->coordinatePlane(), thePrevious);
}
\ No newline at end of file
aProjection->execute();
aRefAttr->setObject(aProjection);
- if (!hasPrevProj) {
- FeaturePtr aFixed = sketch()->addFeature(SketchPlugin_ConstraintRigid::ID());
- aFixed->refattr(SketchPlugin_Constraint::ENTITY_A())->setObject(aProjection->lastResult());
- aFixed->execute();
- }
-
if (theID == EXTERNAL_FEATURE_ID()) {
selection(EXTERNAL_ID())->setValue(aExtFeature->context(), aExtFeature->value());
--- /dev/null
+"""
+ Test1061.py
+ Test case for issue #1061 "Distance constraint using for points with equal coordinates"
+"""
+
+import math
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(70, 120, 50, 25)
+SketchLine_2 = Sketch_1.addLine(50, 25, 170, 50)
+
+DISTANCE = 100
+SketchConstraintDistance_1 = Sketch_1.setDistance(SketchLine_1.endPoint(), SketchLine_2.startPoint(), DISTANCE)
+model.do()
+
+# check distance between points
+aDist2 = (SketchLine_1.endPoint().x() - SketchLine_2.startPoint().x())**2 + (SketchLine_1.endPoint().y() - SketchLine_2.startPoint().y())**2
+assert(math.fabs(aDist2 - DISTANCE**2) > 1e-12)
+
+model.end()
+
+assert(model.checkPythonDump())
aSession.startOperation()
aSketchArc = aSketchFeature.addFeature("SketchArc")
anArcCentr = geomDataAPI_Point2D(aSketchArc.attribute("ArcCenter"))
-anArcStartPoint = geomDataAPI_Point2D(
- aSketchArc.attribute("ArcStartPoint"))
+anArcStartPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcStartPoint"))
anArcEndPoint = geomDataAPI_Point2D(aSketchArc.attribute("ArcEndPoint"))
anArcCentr.setValue(10., 10.)
anArcStartPoint.setValue(0., 50.)
#=========================================================================
# Check values and move one constrainted object
#=========================================================================
-assert (anArcEndPoint.x() == 50)
-assert (anArcEndPoint.y() == 0)
-assert (aLineStartPoint.x() == 50)
-assert (aLineStartPoint.y() == 0)
+assert (anArcEndPoint.x() == aLineStartPoint.x())
+assert (anArcEndPoint.y() == aLineStartPoint.y())
deltaX = deltaY = 40.
# move line
aSession.startOperation()
aConstraint.execute()
aSession.finishOperation()
checkPointOnArc(aCircleCenter, aSketchArc)
+# check center of circle is still in origin
+assert (aCircleCenter.x() == 0. and aCircleCenter.y() == 0.)
+
#=========================================================================
-# Check center of circle is still in origin
+# Create two more lines and set multi-coincidence between their extremities
#=========================================================================
-assert (aCircleCenter.x() == 0. and aCircleCenter.y() == 0.)
+aSession.startOperation()
+# line 2
+aLine2 = aSketchFeature.addFeature("SketchLine")
+aLine2StartPoint = geomDataAPI_Point2D(aLine2.attribute("StartPoint"))
+aLine2EndPoint = geomDataAPI_Point2D(aLine2.attribute("EndPoint"))
+aLine2StartPoint.setValue(50., 0.)
+aLine2EndPoint.setValue(100., 0.)
+# line 3
+aLine3 = aSketchFeature.addFeature("SketchLine")
+aLine3StartPoint = geomDataAPI_Point2D(aLine3.attribute("StartPoint"))
+aLine3EndPoint = geomDataAPI_Point2D(aLine3.attribute("EndPoint"))
+aLine3StartPoint.setValue(50., 0.)
+aLine3EndPoint.setValue(0., 100.)
+aSession.finishOperation()
+# coincidences between extremities of lines
+aSession.startOperation()
+aConstraint12 = aSketchFeature.addFeature("SketchConstraintCoincidence")
+refAttrA = aConstraint12.refattr("ConstraintEntityA")
+refAttrB = aConstraint12.refattr("ConstraintEntityB")
+refAttrA.setAttr(aLineStartPoint)
+refAttrB.setAttr(aLine2StartPoint)
+aConstraint23 = aSketchFeature.addFeature("SketchConstraintCoincidence")
+refAttrA = aConstraint23.refattr("ConstraintEntityA")
+refAttrB = aConstraint23.refattr("ConstraintEntityB")
+refAttrA.setAttr(aLine2StartPoint)
+refAttrB.setAttr(aLine3StartPoint)
+aConstraint31 = aSketchFeature.addFeature("SketchConstraintCoincidence")
+refAttrA = aConstraint31.refattr("ConstraintEntityA")
+refAttrB = aConstraint31.refattr("ConstraintEntityB")
+refAttrA.setAttr(aLine3StartPoint)
+refAttrB.setAttr(aLineStartPoint)
+aSession.finishOperation()
+# check the points have same coordinates
+assert (aLineStartPoint.x() == aLine2StartPoint.x() and aLineStartPoint.y() == aLine2StartPoint.y())
+assert (aLineStartPoint.x() == aLine3StartPoint.x() and aLineStartPoint.y() == aLine3StartPoint.y())
+#=========================================================================
+# Move one line and check other have been updated too
+#=========================================================================
+aSession.startOperation()
+aLine3StartPoint.setValue(aLine3StartPoint.x() + deltaX,
+ aLine3StartPoint.y() + deltaY)
+aLine3EndPoint.setValue(aLine3EndPoint.x() + deltaX,
+ aLine3EndPoint.y() + deltaY)
+aSession.finishOperation()
+assert (aLineStartPoint.x() == aLine2StartPoint.x() and aLineStartPoint.y() == aLine2StartPoint.y())
+assert (aLineStartPoint.x() == aLine3StartPoint.x() and aLineStartPoint.y() == aLine3StartPoint.y())
+#=========================================================================
+# Fix a line and move another connected segment
+#=========================================================================
+coordX = aLineStartPoint.x()
+coordY = aLineStartPoint.y()
+aSession.startOperation()
+aFixed = aSketchFeature.addFeature("SketchConstraintRigid")
+refAttrA = aFixed.refattr("ConstraintEntityA")
+refAttrA.setObject(aLine2.lastResult())
+aSession.finishOperation()
+# move another line
+aSession.startOperation()
+aLine3StartPoint.setValue(aLine3StartPoint.x() + deltaX,
+ aLine3StartPoint.y() + deltaY)
+aLine3EndPoint.setValue(aLine3EndPoint.x() + deltaX,
+ aLine3EndPoint.y() + deltaY)
+aSession.finishOperation()
+assert (aLineStartPoint.x() == coordX and aLineStartPoint.y() == coordY)
+assert (aLine2StartPoint.x() == coordX and aLine2StartPoint.y() == coordY)
+assert (aLine3StartPoint.x() == coordX and aLine3StartPoint.y() == coordY)
+#=========================================================================
+# Detach fixed line and move one of remaining
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aConstraint12)
+aDocument.removeFeature(aConstraint23)
+aSession.finishOperation()
+# move line
+deltaX = 1.
+deltaY = 0.
+aSession.startOperation()
+aLineStartPoint.setValue(aLineStartPoint.x() + deltaX,
+ aLineStartPoint.y() + deltaY)
+aLineEndPoint.setValue(aLineEndPoint.x() + deltaX,
+ aLineEndPoint.y() + deltaY)
+aSession.finishOperation()
+assert (aLineStartPoint.x() != aLine2StartPoint.x() or aLineStartPoint.y() != aLine2StartPoint.y())
+assert (aLineStartPoint.x() == aLine3StartPoint.x() and aLineStartPoint.y() == aLine3StartPoint.y())
+
#=========================================================================
# End of test
#=========================================================================
reflistB.setObject(aLine1.lastResult())
aConstraint.execute()
aSession.finishOperation()
+#=========================================================================
+# Check error message (this message is not a error but a limitation of PlaneGCS)
+# If the problem will be resolved, following block may be removed
+#=========================================================================
+assert aSketchFeature.string("SolverError").value() != "", "PlaneGCS limitation: if you see this message, then PlaneGCS has solved conflicting constraints when applying Middle constraint for the point out of the segment"
+aSession.startOperation()
+aDocument.removeFeature(aConstraint)
+aSession.finishOperation()
+aSession.startOperation()
+aEndPoint2.setValue(80., 25.)
+aConstraint = aSketchFeature.addFeature("SketchConstraintMiddle")
+reflistA = aConstraint.refattr("ConstraintEntityA")
+reflistB = aConstraint.refattr("ConstraintEntityB")
+reflistA.setAttr(aEndPoint2)
+reflistB.setObject(aLine1.lastResult())
+aConstraint.execute()
+aSession.finishOperation()
+
#=========================================================================
# Check values and move one constrainted object
#=========================================================================
# Check origin coordinates does not changed
#=========================================================================
assert (anOriginCoord.x() == 0. and anOriginCoord.y() == 0.)
+
+#=========================================================================
+# Add other line with one extremity coincident to the first line
+#=========================================================================
+aSession.startOperation()
+aLine3 = aSketchFeature.addFeature("SketchLine")
+aStartPoint3 = geomDataAPI_Point2D(aLine3.attribute("StartPoint"))
+aEndPoint3 = geomDataAPI_Point2D(aLine3.attribute("EndPoint"))
+aStartPoint3.setValue(50., 50.)
+aEndPoint3.setValue(50., 0.)
+aCoincidence = aSketchFeature.addFeature("SketchConstraintCoincidence")
+reflistA = aCoincidence.refattr("ConstraintEntityA")
+reflistB = aCoincidence.refattr("ConstraintEntityB")
+reflistA.setAttr(aEndPoint3)
+reflistB.setObject(aLine1.lastResult())
+aSession.finishOperation()
+#=========================================================================
+# Set Middle point
+#=========================================================================
+aSession.startOperation()
+aMiddle = aSketchFeature.addFeature("SketchConstraintMiddle")
+reflistA = aMiddle.refattr("ConstraintEntityA")
+reflistB = aMiddle.refattr("ConstraintEntityB")
+reflistA.setAttr(aEndPoint3)
+reflistB.setObject(aLine1.lastResult())
+aSession.finishOperation()
+# check the point, and no error message
+assert aSketchFeature.string("SolverError").value() == ""
+checkMiddlePoint(aEndPoint3, aLine1)
+#=========================================================================
+# Remove coincidence and move one line
+#=========================================================================
+aSession.startOperation()
+aDocument.removeFeature(aCoincidence)
+aSession.finishOperation()
+deltaX, deltaY = 10.0, -10.0
+aSession.startOperation()
+aStartPoint1.setValue(aStartPoint1.x() + deltaX, aStartPoint1.y() + deltaY)
+aEndPoint1.setValue(aEndPoint1.x() + deltaX, aEndPoint1.y() + deltaY)
+aSession.finishOperation()
+checkMiddlePoint(aEndPoint3, aLine1)
+
#=========================================================================
# End of test
#=========================================================================
assert(aFeatureC is not None)
assert(aFeatureB.getKind() == aFeatureC.getKind())
- anAttributes = {}
+ anAttributes = []
if (aFeatureB.getKind() == "SketchLine"):
- anAttributes = {'StartPoint':'StartPoint', 'EndPoint':'EndPoint'}
+ anAttributes = ['StartPoint', 'EndPoint']
elif (aFeatureB.getKind() == "SketchArc"):
- anAttributes = {'ArcCenter':'ArcCenter', 'ArcStartPoint':'ArcEndPoint', 'ArcEndPoint':'ArcStartPoint'}
+ anAttributes = ['ArcCenter', 'ArcStartPoint', 'ArcEndPoint']
for key in anAttributes:
aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
- aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key]))
+ aPointC = geomDataAPI_Point2D(aFeatureC.attribute(key))
aDir = [aPointC.x() - aPointB.x(), aPointC.y() - aPointB.y()]
aDir = normalize(aDir)
aDot = aLineDir[0] * aDir[0] + aLineDir[1] * aDir[1]
# End of test
#=========================================================================
-from salome.shaper import model
-assert(model.checkPythonDump())
+#from salome.shaper import model
+#assert(model.checkPythonDump())
## Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+# Avoid using SolveSpace
+SET(NO_SolveSpace TRUE)
+
+# Convert files in list to full name
+FUNCTION(TO_FULL_PATH theFILES)
+ SET(locFiles "")
+ FOREACH(locFile ${${theFILES}})
+ SET(locFiles ${locFiles} ${CMAKE_CURRENT_SOURCE_DIR}/${locFile})
+ ENDFOREACH()
+ SET(${theFILES} ${locFiles} PARENT_SCOPE)
+ENDFUNCTION(TO_FULL_PATH)
+
+
INCLUDE(Common)
-SET(PROJECT_HEADERS
+SET(SKETCHSOLVER_HEADERS
SketchSolver.h
SketchSolver_Error.h
+ SketchSolver_Group.h
+ SketchSolver_Builder.h
+ SketchSolver_IConstraintWrapper.h
+ SketchSolver_IEntityWrapper.h
+ SketchSolver_ISolver.h
+ SketchSolver_Manager.h
+ SketchSolver_Storage.h
+)
+
+SET(SKETCHSOLVER_CONSTRAINT_HEADERS
SketchSolver_Constraint.h
SketchSolver_ConstraintAngle.h
SketchSolver_ConstraintCoincidence.h
SketchSolver_ConstraintMiddle.h
SketchSolver_ConstraintMirror.h
SketchSolver_ConstraintFixed.h
- SketchSolver_ConstraintFixedArcRadius.h
SketchSolver_ConstraintTangent.h
SketchSolver_ConstraintMulti.h
SketchSolver_ConstraintMultiRotation.h
SketchSolver_ConstraintMultiTranslation.h
- SketchSolver_ConstraintMovement.h
- SketchSolver_Group.h
- SketchSolver_Builder.h
- SketchSolver_IConstraintWrapper.h
- SketchSolver_IEntityWrapper.h
- SketchSolver_IParameterWrapper.h
- SketchSolver_ISolver.h
- SketchSolver_Manager.h
- SketchSolver_Storage.h
)
-SET(PROJECT_SOURCES
+SET(SKETCHSOLVER_SOURCES
+ SketchSolver_Group.cpp
+ SketchSolver_Builder.cpp
+ SketchSolver_Manager.cpp
+ SketchSolver_Storage.cpp
+)
+
+SET(SKETCHSOLVER_CONSTRAINT_SOURCES
SketchSolver_Constraint.cpp
SketchSolver_ConstraintAngle.cpp
SketchSolver_ConstraintCoincidence.cpp
SketchSolver_ConstraintMiddle.cpp
SketchSolver_ConstraintMirror.cpp
SketchSolver_ConstraintFixed.cpp
- SketchSolver_ConstraintFixedArcRadius.cpp
SketchSolver_ConstraintTangent.cpp
SketchSolver_ConstraintMulti.cpp
SketchSolver_ConstraintMultiRotation.cpp
SketchSolver_ConstraintMultiTranslation.cpp
- SketchSolver_ConstraintMovement.cpp
- SketchSolver_Group.cpp
- SketchSolver_Builder.cpp
- SketchSolver_Manager.cpp
- SketchSolver_Storage.cpp
)
-SET(PROJECT_LIBRARIES
+SET(SKETCHSOLVER_LIBRARIES
Config
Events
ModelAPI
GeomDataAPI
)
-SET(TEXT_RESOURCES
+SET(SKETCHSOLVER_TEXT_RESOURCES
SketchSolver_msg_en.ts
)
${PROJECT_SOURCE_DIR}/src/Events
)
-SOURCE_GROUP ("Resource Files" FILES ${TEXT_RESOURCES})
-
-ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS)
-
-ADD_LIBRARY(SketchSolver SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${TEXT_RESOURCES}
-)
-
-TARGET_LINK_LIBRARIES(SketchSolver ${PROJECT_LIBRARIES}
-)
+#SOURCE_GROUP ("Resource Files" FILES ${SKETCHSOLVER_TEXT_RESOURCES})
+#
+#ADD_DEFINITIONS(-DSKETCHSOLVER_EXPORTS)
+#
+#ADD_LIBRARY(SketchSolver SHARED ${SKETCHSOLVER_SOURCES} ${SKETCHSOLVER_CONSTRAINT_SOURCES} ${SKETCHSOLVER_HEADERS} ${SKETCHSOLVER_CONSTRAINT_HEADERS} ${SKETCHSOLVER_TEXT_RESOURCES}
+#)
+#
+#TARGET_LINK_LIBRARIES(SketchSolver ${SKETCHSOLVER_LIBRARIES}
+#)
+#
+#INSTALL(TARGETS SketchSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
+#INSTALL(FILES ${SKETCHSOLVER_TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
-INSTALL(TARGETS SketchSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
-INSTALL(FILES ${TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
+# Set full path to source files
+TO_FULL_PATH(SKETCHSOLVER_SOURCES)
+TO_FULL_PATH(SKETCHSOLVER_CONSTRAINT_SOURCES)
+TO_FULL_PATH(SKETCHSOLVER_HEADERS)
+TO_FULL_PATH(SKETCHSOLVER_CONSTRAINT_HEADERS)
+TO_FULL_PATH(SKETCHSOLVER_TEXT_RESOURCES)
# Include specific solvers
FIND_PACKAGE(PlaneGCS REQUIRED)
-SET(PROJECT_HEADERS
+SET(PLANEGCSSOLVER_HEADERS
PlaneGCSSolver_Defs.h
PlaneGCSSolver_Solver.h
PlaneGCSSolver_Builder.h
PlaneGCSSolver_EntityWrapper.h
PlaneGCSSolver_PointWrapper.h
PlaneGCSSolver_ScalarWrapper.h
- PlaneGCSSolver_ParameterWrapper.h
PlaneGCSSolver_AngleWrapper.h
)
-SET(PROJECT_SOURCES
+SET(PLANEGCSSOLVER_SOURCES
PlaneGCSSolver_Solver.cpp
PlaneGCSSolver_Builder.cpp
PlaneGCSSolver_Storage.cpp
PlaneGCSSolver_EntityWrapper.cpp
PlaneGCSSolver_PointWrapper.cpp
PlaneGCSSolver_ScalarWrapper.cpp
- PlaneGCSSolver_ParameterWrapper.cpp
PlaneGCSSolver_AngleWrapper.cpp
)
+SET(PLANEGCSSOLVER_BUILDER_HEADERS
+ PlaneGCSSolver_EntityBuilder.h
+ PlaneGCSSolver_AttributeBuilder.h
+ PlaneGCSSolver_FeatureBuilder.h
+ PlaneGCSSolver_EntityDestroyer.h
+)
+
+SET(PLANEGCSSOLVER_BUILDER_SOURCES
+ PlaneGCSSolver_AttributeBuilder.cpp
+ PlaneGCSSolver_FeatureBuilder.cpp
+ PlaneGCSSolver_EntityDestroyer.cpp
+)
+
+SET(PLANEGCSSOLVER_UPDATER_HEADERS
+ PlaneGCSSolver_Update.h
+ PlaneGCSSolver_UpdateFeature.h
+ PlaneGCSSolver_UpdateCoincidence.h
+)
+
+SET(PLANEGCSSOLVER_UPDATER_SOURCES
+ PlaneGCSSolver_UpdateFeature.cpp
+ PlaneGCSSolver_UpdateCoincidence.cpp
+)
+
SET(PROJECT_LIBRARIES
${PLANEGCS_LIBRARIES}
- SketchSolver
- ModelAPI
- GeomAPI
+ ${SKETCHSOLVER_LIBRARIES}
)
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/src/GeomDataAPI
)
+SOURCE_GROUP ("Resource Files" FILES ${SKETCHSOLVER_TEXT_RESOURCES})
+SOURCE_GROUP ("Header Files\\Builders" FILES ${PLANEGCSSOLVER_BUILDER_HEADERS})
+SOURCE_GROUP ("Source Files\\Builders" FILES ${PLANEGCSSOLVER_BUILDER_SOURCES})
+SOURCE_GROUP ("Header Files\\Updaters" FILES ${PLANEGCSSOLVER_UPDATER_HEADERS})
+SOURCE_GROUP ("Source Files\\Updaters" FILES ${PLANEGCSSOLVER_UPDATER_SOURCES})
+SOURCE_GROUP ("Header Files\\SketchSolver" FILES ${SKETCHSOLVER_HEADERS})
+SOURCE_GROUP ("Source Files\\SketchSolver" FILES ${SKETCHSOLVER_SOURCES})
+SOURCE_GROUP ("Header Files\\Constraints" FILES ${SKETCHSOLVER_CONSTRAINT_HEADERS})
+SOURCE_GROUP ("Source Files\\Constraints" FILES ${SKETCHSOLVER_CONSTRAINT_SOURCES})
+SOURCE_GROUP ("Header Files\\PlaneGCS" FILES ${PLANEGCSSOLVER_HEADERS})
+SOURCE_GROUP ("Source Files\\PlaneGCS" FILES ${PLANEGCSSOLVER_SOURCES})
+
+SET(PROJECT_HEADERS
+ ${PLANEGCSSOLVER_HEADERS}
+ ${PLANEGCSSOLVER_BUILDER_HEADERS}
+ ${PLANEGCSSOLVER_UPDATER_HEADERS}
+ ${SKETCHSOLVER_HEADERS}
+ ${SKETCHSOLVER_CONSTRAINT_HEADERS}
+)
+
+SET(PROJECT_SOURCES
+ ${PLANEGCSSOLVER_SOURCES}
+ ${PLANEGCSSOLVER_BUILDER_SOURCES}
+ ${PLANEGCSSOLVER_UPDATER_SOURCES}
+ ${SKETCHSOLVER_SOURCES}
+ ${SKETCHSOLVER_CONSTRAINT_SOURCES}
+)
-ADD_LIBRARY(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS})
-TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES})
+ADD_LIBRARY(PlaneGCSSolver MODULE ${PROJECT_SOURCES} ${PROJECT_HEADERS} ${SKETCHSOLVER_TEXT_RESOURCES})
+TARGET_LINK_LIBRARIES(PlaneGCSSolver ${PROJECT_LIBRARIES} ${SKETCHSOLVER_LIBRARIES})
INSTALL(TARGETS PlaneGCSSolver DESTINATION ${SHAPER_INSTALL_PLUGIN_FILES})
+INSTALL(FILES ${SKETCHSOLVER_TEXT_RESOURCES} DESTINATION ${SHAPER_INSTALL_XML_RESOURCES})
#include <PlaneGCSSolver_AngleWrapper.h>
-#include <math.h>
+#include <cmath>
static double deg2rad(double theDegrees)
{
}
PlaneGCSSolver_AngleWrapper::PlaneGCSSolver_AngleWrapper(double *const theParam)
- : PlaneGCSSolver_ParameterWrapper(theParam)
+ : PlaneGCSSolver_ScalarWrapper(theParam)
{
- setValue(*myValue);
+ setValue(*theParam);
}
void PlaneGCSSolver_AngleWrapper::setValue(double theValue)
#ifndef PlaneGCSSolver_AngleWrapper_H_
#define PlaneGCSSolver_AngleWrapper_H_
-#include <PlaneGCSSolver_ParameterWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
/**
* Wrapper providing operations with angular parameters in PlaneGCS.
+ * Provides automatic conversion from degrees to radians and vice versa.
*/
-class PlaneGCSSolver_AngleWrapper : public PlaneGCSSolver_ParameterWrapper
+class PlaneGCSSolver_AngleWrapper : public PlaneGCSSolver_ScalarWrapper
{
public:
PlaneGCSSolver_AngleWrapper(double *const theParam);
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_AttributeBuilder.cpp
+// Created: 10 Feb 2017
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_AngleWrapper.h>
+#include <PlaneGCSSolver_AttributeBuilder.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+
+#include <GeomDataAPI_Point2D.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <SketchPlugin_ConstraintAngle.h>
+#include <SketchPlugin_MultiRotation.h>
+
+PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(
+ PlaneGCSSolver_Storage* theStorage)
+ : PlaneGCSSolver_EntityBuilder(theStorage)
+{
+}
+
+PlaneGCSSolver_AttributeBuilder::PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage)
+ : PlaneGCSSolver_EntityBuilder(
+ std::dynamic_pointer_cast<PlaneGCSSolver_Storage>(theStorage).get())
+{
+}
+
+static double* createParameter(PlaneGCSSolver_Storage* theStorage)
+{
+ return theStorage ? theStorage->createParameter() : (new double(0));
+}
+
+static EntityWrapperPtr createScalar(const AttributePtr& theAttribute,
+ PlaneGCSSolver_Storage* theStorage)
+{
+ AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+ if (!aScalar)
+ return EntityWrapperPtr();
+
+ ScalarWrapperPtr aWrapper;
+ // following attributes should be converted from degrees to radians
+ // - value of the Angle constraint
+ // - angle of the Multi-Rotation constraint
+ FeaturePtr anOwner = ModelAPI_Feature::feature(theAttribute->owner());
+ if ((theAttribute->id() == SketchPlugin_Constraint::VALUE() &&
+ anOwner->getKind() == SketchPlugin_ConstraintAngle::ID()) ||
+ (theAttribute->id() == SketchPlugin_MultiRotation::ANGLE_ID() &&
+ anOwner->getKind() == SketchPlugin_MultiRotation::ID()))
+ aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_AngleWrapper(createParameter(theStorage)));
+ else
+ aWrapper = ScalarWrapperPtr(new PlaneGCSSolver_ScalarWrapper(createParameter(theStorage)));
+
+ aWrapper->setValue(aScalar->value());
+ return aWrapper;
+}
+
+static EntityWrapperPtr createPoint(const AttributePtr& theAttribute,
+ PlaneGCSSolver_Storage* theStorage)
+{
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
+ if (!aPoint2D)
+ return EntityWrapperPtr();
+
+ GCSPointPtr aNewPoint(new GCS::Point);
+
+ aNewPoint->x = createParameter(theStorage);
+ *(aNewPoint->x) = aPoint2D->x();
+ aNewPoint->y = createParameter(theStorage);
+ *(aNewPoint->y) = aPoint2D->y();
+
+ return EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(aNewPoint));
+}
+
+EntityWrapperPtr PlaneGCSSolver_AttributeBuilder::createAttribute(
+ AttributePtr theAttribute)
+{
+ EntityWrapperPtr aResult;
+ if (myStorage)
+ aResult = myStorage->entity(theAttribute);
+ if (!aResult)
+ aResult = createPoint(theAttribute, myStorage);
+ if (!aResult)
+ aResult = createScalar(theAttribute, myStorage);
+ if (aResult && !myStorage)
+ aResult->setExternal(true);
+ return aResult;
+}
+
+const std::list<GCSConstraintPtr>& PlaneGCSSolver_AttributeBuilder::constraints() const
+{
+ static std::list<GCSConstraintPtr> aList;
+ return aList;
+}
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_AttributeBuilder.h
+// Created: 10 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_AttributeBuilder_H_
+#define PlaneGCSSolver_AttributeBuilder_H_
+
+#include <PlaneGCSSolver_EntityBuilder.h>
+
+/** \class PlaneGCSSolver_AttributeBuilder
+ * \ingroup Plugins
+ * \brief Converts ModelAPI_Attribute to the entity applicable for PlaneGCS solver
+ */
+class PlaneGCSSolver_AttributeBuilder : public PlaneGCSSolver_EntityBuilder
+{
+public:
+ PlaneGCSSolver_AttributeBuilder(PlaneGCSSolver_Storage* theStorage = 0);
+ PlaneGCSSolver_AttributeBuilder(const StoragePtr& theStorage);
+
+ /// \brief Converts an attribute to the solver's entity.
+ /// Double attributes and 2D points are supported only.
+ /// \param theAttribute [in] attribute to create
+ /// \return Created wrapper of the attribute applicable for specific solver
+ virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute) override;
+
+ /// \brief Blank. To be defined in derived class.
+ virtual EntityWrapperPtr createFeature(FeaturePtr) override
+ { return EntityWrapperPtr(); }
+
+ /// \brief Blank. To be defined in derived class.
+ virtual const std::list<GCSConstraintPtr>& constraints() const override;
+};
+
+#endif
// Author: Artem ZHIDKOV
#include <PlaneGCSSolver_Builder.h>
-#include <PlaneGCSSolver_Solver.h>
#include <PlaneGCSSolver_Storage.h>
-#include <PlaneGCSSolver_ParameterWrapper.h>
-#include <PlaneGCSSolver_AngleWrapper.h>
#include <PlaneGCSSolver_EntityWrapper.h>
#include <PlaneGCSSolver_PointWrapper.h>
#include <PlaneGCSSolver_ScalarWrapper.h>
#include <SketchSolver_Manager.h>
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <GeomDataAPI_Dir.h>
-#include <GeomDataAPI_Point.h>
#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_AttributeRefAttr.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-#include <SketchPlugin_IntersectionPoint.h>
#include <SketchPlugin_ConstraintAngle.h>
-#include <math.h>
+#include <cmath>
#define GCS_ENTITY_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(x)
-#define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
-#define GCS_PARAMETER_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(x)
-
-
-/// \brief Converts a value to SolveSpace parameter
-/// \param theGroup [in] group to store parameter
-/// \param theValue [in] value of parameter
-/// \param theExpr [in] shows the parameter is given by expression
-/// \return Created parameter's wrapper
-static ParameterWrapperPtr createParameter(const GroupID& theGroup,
- const double theValue = 0.0,
- const bool theExpr = false);
-
-static ParameterWrapperPtr createParamAngle(const GroupID& theGroup,
- const double& theValue = 0.0);
-
-static std::shared_ptr<PlaneGCSSolver_ScalarWrapper>
- createScalar(const GroupID& theGroupID,
- AttributeDoublePtr theDoubleAttr = AttributeDoublePtr());
+#define GCS_POINT_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(x)
+#define GCS_SCALAR_WRAPPER(x) std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(x)
-static EntityWrapperPtr createLine(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID);
-static EntityWrapperPtr createCircle(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID);
-static EntityWrapperPtr createArc(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID);
static ConstraintWrapperPtr
- createConstraintCoincidence(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ createConstraintCoincidence(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
static ConstraintWrapperPtr
- createConstraintPointOnEntity(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const SketchSolver_ConstraintType& theType,
+ createConstraintPointOnEntity(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
static ConstraintWrapperPtr
- createConstraintDistancePointPoint(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ createConstraintDistancePointPoint(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2);
static ConstraintWrapperPtr
- createConstraintDistancePointLine(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
- std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ createConstraintDistancePointLine(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
static ConstraintWrapperPtr
- createConstraintRadius(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ createConstraintRadius(std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
static ConstraintWrapperPtr
createConstraintAngle(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
static ConstraintWrapperPtr
- createConstraintHorizVert(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const SketchSolver_ConstraintType& theType,
+ createConstraintHorizVert(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
static ConstraintWrapperPtr
- createConstraintParallel(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ createConstraintParallel(std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
static ConstraintWrapperPtr
- createConstraintPerpendicular(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
+ createConstraintPerpendicular(std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
static ConstraintWrapperPtr
- createConstraintEqual(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const SketchSolver_ConstraintType& theType,
+ createConstraintEqual(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed);
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed);
static ConstraintWrapperPtr
- createConstraintTangent(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const SketchSolver_ConstraintType& theType,
+ createConstraintTangent(const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
static ConstraintWrapperPtr
createConstraintCollinear(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2);
static ConstraintWrapperPtr
- createConstraintMiddlePoint(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ createConstraintMiddlePoint(std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity);
-/// \brief Update mirror points
-static void adjustMirror(ConstraintWrapperPtr theConstraint);
-/// \brief Update a sign of the point-line distance constraint
-static void adjustPtLineDistance(ConstraintWrapperPtr theConstraint);
-
-/// \brief Transform points to be symmetric regarding to the mirror line
-static void makeMirrorPoints(EntityWrapperPtr theOriginal,
- EntityWrapperPtr theMirrored,
- EntityWrapperPtr theMirrorLine);
-
-
-
-// Initialization of constraint builder self pointer
-BuilderPtr PlaneGCSSolver_Builder::mySelf = PlaneGCSSolver_Builder::getInstance();
+// Initialization of pointer to builder
+static BuilderPtr gBuilder = PlaneGCSSolver_Builder::getInstance();
BuilderPtr PlaneGCSSolver_Builder::getInstance()
{
+ static BuilderPtr mySelf;
if (!mySelf) {
mySelf = BuilderPtr(new PlaneGCSSolver_Builder);
SketchSolver_Manager::instance()->setBuilder(mySelf);
return mySelf;
}
-StoragePtr PlaneGCSSolver_Builder::createStorage(const GroupID& theGroup) const
+StoragePtr PlaneGCSSolver_Builder::createStorage(const SolverPtr& theSolver) const
{
- return StoragePtr(new PlaneGCSSolver_Storage(theGroup));
+ return StoragePtr(new PlaneGCSSolver_Storage(theSolver));
}
SolverPtr PlaneGCSSolver_Builder::createSolver() const
}
-std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
+ConstraintWrapperPtr PlaneGCSSolver_Builder::createConstraint(
ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
const SketchSolver_ConstraintType& theType,
- const double& theValue,
+ const EntityWrapperPtr& theValue,
const EntityWrapperPtr& thePoint1,
const EntityWrapperPtr& thePoint2,
const EntityWrapperPtr& theEntity1,
const EntityWrapperPtr& theEntity2) const
{
ConstraintWrapperPtr aResult;
- ParameterWrapperPtr anIntermediate;
+ ScalarWrapperPtr anIntermediate;
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(thePoint1);
- if (!aPoint1 && thePoint1 && thePoint1->type() == ENTITY_POINT)
- aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint1)->subEntities().front() );
std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(thePoint2);
- if (!aPoint2 && thePoint2 && thePoint2->type() == ENTITY_POINT)
- aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(thePoint2)->subEntities().front() );
switch (theType) {
case CONSTRAINT_PT_PT_COINCIDENT:
- aResult = createConstraintCoincidence(theConstraint, theGroupID, aPoint1, aPoint2);
+ aResult = createConstraintCoincidence(aPoint1, aPoint2);
break;
case CONSTRAINT_PT_ON_LINE:
case CONSTRAINT_PT_ON_CIRCLE:
- aResult = createConstraintPointOnEntity(theConstraint, theGroupID, theType,
- aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
+ aResult = createConstraintPointOnEntity(theType, aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
break;
case CONSTRAINT_MIDDLE_POINT:
- aResult = createConstraintMiddlePoint(theConstraint, theGroupID,
- aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
+ aResult = createConstraintMiddlePoint(aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
break;
case CONSTRAINT_PT_PT_DISTANCE:
- aResult = createConstraintDistancePointPoint(theConstraint, theGroupID,
- GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
- aPoint1, aPoint2);
+ aResult = createConstraintDistancePointPoint(GCS_SCALAR_WRAPPER(theValue), aPoint1, aPoint2);
break;
case CONSTRAINT_PT_LINE_DISTANCE:
- aResult = createConstraintDistancePointLine(theConstraint, theGroupID,
- GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
- aPoint1, GCS_ENTITY_WRAPPER(theEntity1));
+ aResult = createConstraintDistancePointLine(GCS_SCALAR_WRAPPER(theValue),
+ aPoint1,
+ GCS_ENTITY_WRAPPER(theEntity1));
break;
case CONSTRAINT_RADIUS:
- aResult = createConstraintRadius(theConstraint, theGroupID,
- GCS_PARAMETER_WRAPPER(createParameter(GID_OUTOFGROUP, theValue)),
- GCS_ENTITY_WRAPPER(theEntity1));
+ aResult = createConstraintRadius(GCS_SCALAR_WRAPPER(theValue),
+ GCS_ENTITY_WRAPPER(theEntity1));
break;
case CONSTRAINT_ANGLE:
- aResult = createConstraintAngle(theConstraint, theGroupID,
- GCS_PARAMETER_WRAPPER(createParamAngle(GID_OUTOFGROUP, theValue)),
+ aResult = createConstraintAngle(theConstraint,
+ GCS_SCALAR_WRAPPER(theValue),
GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
break;
case CONSTRAINT_FIXED:
break;
case CONSTRAINT_HORIZONTAL:
case CONSTRAINT_VERTICAL:
- aResult = createConstraintHorizVert(theConstraint, theGroupID, theType,
- GCS_ENTITY_WRAPPER(theEntity1));
+ aResult = createConstraintHorizVert(theType, GCS_ENTITY_WRAPPER(theEntity1));
break;
case CONSTRAINT_PARALLEL:
- aResult = createConstraintParallel(theConstraint, theGroupID,
- GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ aResult = createConstraintParallel(GCS_ENTITY_WRAPPER(theEntity1),
+ GCS_ENTITY_WRAPPER(theEntity2));
break;
case CONSTRAINT_PERPENDICULAR:
- aResult = createConstraintPerpendicular(theConstraint, theGroupID,
- GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ aResult = createConstraintPerpendicular(GCS_ENTITY_WRAPPER(theEntity1),
+ GCS_ENTITY_WRAPPER(theEntity2));
break;
case CONSTRAINT_EQUAL_LINES:
- anIntermediate = createParameter(theGroupID);
+ anIntermediate = GCS_SCALAR_WRAPPER(theValue); // parameter is used to store length of lines
case CONSTRAINT_EQUAL_LINE_ARC:
case CONSTRAINT_EQUAL_RADIUS:
- aResult = createConstraintEqual(theConstraint, theGroupID, theType,
- GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2),
- GCS_PARAMETER_WRAPPER(anIntermediate));
+ aResult = createConstraintEqual(theType,
+ GCS_ENTITY_WRAPPER(theEntity1),
+ GCS_ENTITY_WRAPPER(theEntity2),
+ anIntermediate);
break;
case CONSTRAINT_TANGENT_ARC_LINE:
case CONSTRAINT_TANGENT_CIRCLE_LINE:
case CONSTRAINT_TANGENT_ARC_ARC:
- aResult = createConstraintTangent(theConstraint, theGroupID, theType,
- GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
+ aResult = createConstraintTangent(theType,
+ GCS_ENTITY_WRAPPER(theEntity1),
+ GCS_ENTITY_WRAPPER(theEntity2));
break;
case CONSTRAINT_COLLINEAR:
- aResult = createConstraintCollinear(theConstraint, theGroupID,
+ aResult = createConstraintCollinear(theConstraint,
GCS_ENTITY_WRAPPER(theEntity1), GCS_ENTITY_WRAPPER(theEntity2));
break;
case CONSTRAINT_MULTI_TRANSLATION:
case CONSTRAINT_MULTI_ROTATION:
- break;
case CONSTRAINT_SYMMETRIC:
- return createMirror(theConstraint, theGroupID, theSketchID,
- thePoint1, thePoint2, theEntity1);
default:
break;
}
- if (!aResult)
- return std::list<ConstraintWrapperPtr>();
- adjustConstraint(aResult);
- return std::list<ConstraintWrapperPtr>(1, aResult);
+ return aResult;
}
-std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createConstraint(
+ConstraintWrapperPtr PlaneGCSSolver_Builder::createConstraint(
ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
const SketchSolver_ConstraintType& theType,
- const double& theValue,
+ const EntityWrapperPtr& theValue,
const bool theFullValue,
const EntityWrapperPtr& thePoint1,
const EntityWrapperPtr& thePoint2,
const std::list<EntityWrapperPtr>& theTrsfEnt) const
{
- ParameterWrapperPtr anAngleParam;
- if (theType == CONSTRAINT_MULTI_ROTATION)
- anAngleParam = createParamAngle(theGroupID, theValue);
- else if (theType != CONSTRAINT_MULTI_TRANSLATION)
- return std::list<ConstraintWrapperPtr>();
+ if (theType != CONSTRAINT_MULTI_ROTATION && theType != CONSTRAINT_MULTI_TRANSLATION)
+ return ConstraintWrapperPtr();
std::list<EntityWrapperPtr> aConstrAttrList = theTrsfEnt;
if (thePoint2)
aConstrAttrList.push_front(thePoint2);
aConstrAttrList.push_front(thePoint1);
+ ScalarWrapperPtr aValue = GCS_SCALAR_WRAPPER(theValue);
+
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, std::list<GCSConstraintPtr>(), theType));
- aResult->setGroup(theGroupID);
+ new PlaneGCSSolver_ConstraintWrapper(std::list<GCSConstraintPtr>(), theType));
aResult->setEntities(aConstrAttrList);
- if (anAngleParam)
- aResult->setValueParameter(anAngleParam);
+ if (aValue)
+ aResult->setValueParameter(aValue);
aResult->setIsFullValue(theFullValue);
- return std::list<ConstraintWrapperPtr>(1, aResult);
-}
-
-
-std::list<ConstraintWrapperPtr> PlaneGCSSolver_Builder::createMirror(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2,
- const EntityWrapperPtr& theMirrorLine) const
-{
- std::list<ConstraintWrapperPtr> aResult;
- std::list<EntityWrapperPtr> aConstrAttrList;
- if (theEntity1->type() == ENTITY_POINT) {
- if (theEntity2->group() == theGroupID) // theEntity2 is not fixed
- makeMirrorPoints(theEntity1, theEntity2, theMirrorLine);
-
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint1 = GCS_POINT_WRAPPER(theEntity1);
- if (!aPoint1 && theEntity1->type() == ENTITY_POINT)
- aPoint1 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity1)->subEntities().front() );
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint2 = GCS_POINT_WRAPPER(theEntity2);
- if (!aPoint2 && theEntity2->type() == ENTITY_POINT)
- aPoint2 = GCS_POINT_WRAPPER( GCS_ENTITY_WRAPPER(theEntity2)->subEntities().front() );
-
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> aMirrorLine =
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMirrorLine);
- std::shared_ptr<GCS::Line> aLine =
- std::dynamic_pointer_cast<GCS::Line>(aMirrorLine->entity());
-
- std::list<GCSConstraintPtr> aConstrList;
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintMidpointOnLine(
- *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPerpendicular(
- *(aPoint1->point()), *(aPoint2->point()), aLine->p1, aLine->p2)));
-
- ConstraintWrapperPtr aSubResult(new PlaneGCSSolver_ConstraintWrapper(
- theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
- aSubResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aSubs.push_back(theMirrorLine);
- aSubResult->setEntities(aSubs);
- aResult.push_back(aSubResult);
- }
- else if (theEntity1->type() == ENTITY_LINE) {
- const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
- const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
- std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
- for (; anIt1 != aPoints1.end() && anIt2 != aPoints2.end(); ++anIt1, ++anIt2) {
- std::list<ConstraintWrapperPtr> aMrrList =
- createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
- }
- }
- else if (theEntity1->type() == ENTITY_CIRCLE) {
- const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt1 = aPoints1.begin();
- for (; anIt1 != aPoints1.end(); ++anIt1)
- if ((*anIt1)->type() == ENTITY_POINT)
- break;
- const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt2 = aPoints2.begin();
- for (; anIt2 != aPoints2.end(); ++anIt2)
- if ((*anIt2)->type() == ENTITY_POINT)
- break;
-
- std::list<ConstraintWrapperPtr> aMrrList =
- createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
- // Additional constraint for equal radii
- aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
- 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
- }
- else if (theEntity1->type() == ENTITY_ARC) {
- // Do not allow mirrored arc recalculate its position until
- // coordinated of all points recalculated
- FeaturePtr aMirrArc = theEntity2->baseFeature();
- bool aWasBlocked = aMirrArc->data()->blockSendAttributeUpdated(true);
-
- // Make mirror for center and start point of original arc
- std::list<ConstraintWrapperPtr> aMrrList;
- std::list<EntityWrapperPtr>::const_iterator anIt1 = theEntity1->subEntities().begin();
- std::list<EntityWrapperPtr>::const_iterator anIt2 = theEntity2->subEntities().begin();
- aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
- ++anIt1;
- ++anIt2; ++anIt2;
- aMrrList = createMirror(theConstraint, theGroupID, theSketchID, *anIt1, *anIt2, theMirrorLine);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
-
- // make symmetric last point of original arc and first point of
- // mirrored arc without additional constraint
- ++anIt1;
- --anIt2;
- makeMirrorPoints(*anIt1, *anIt2, theMirrorLine);
-
- // Additionally, make equal radii...
- aMrrList = createConstraint(theConstraint, theGroupID, theSketchID, CONSTRAINT_EQUAL_RADIUS,
- 0.0, EntityWrapperPtr(), EntityWrapperPtr(), theEntity1, theEntity2);
- aResult.insert(aResult.end(), aMrrList.begin(), aMrrList.end());
- // ... and make parametric length of arcs the same
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt1 =
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity1);
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt2 =
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity2);
- std::shared_ptr<GCS::Arc> anArc1 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt1->entity());
- std::shared_ptr<GCS::Arc> anArc2 = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt2->entity());
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> anIntermed =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
- createParameter(theGroupID, *(anArc1->endAngle) - *(anArc1->startAngle)));
- // By the way, recalculate start and end angles of mirrored arc
- std::shared_ptr<GeomAPI_Dir2d> anOX(new GeomAPI_Dir2d(1.0, 0.0));
- std::shared_ptr<GeomAPI_Dir2d> aStartDir(new GeomAPI_Dir2d(
- *(anArc2->start.x) - *(anArc2->center.x), *(anArc2->start.y) - *(anArc2->center.y)));
- std::shared_ptr<GeomAPI_Dir2d> aEndDir(new GeomAPI_Dir2d(
- *(anArc2->end.x) - *(anArc2->center.x), *(anArc2->end.y) - *(anArc2->center.y)));
- *anArc2->startAngle = anOX->angle(aStartDir);
- *anArc2->endAngle = anOX->angle(aEndDir);
-
- std::list<GCSConstraintPtr> aConstrList;
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
- anArc1->endAngle, anArc1->startAngle, anIntermed->parameter())));
- aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintDifference(
- anArc2->endAngle, anArc2->startAngle, anIntermed->parameter())));
-
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aSubResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, CONSTRAINT_SYMMETRIC));
- aSubResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aSubs.push_back(theMirrorLine);
- aSubResult->setEntities(aSubs);
- aSubResult->setValueParameter(anIntermed);
- aResult.push_back(aSubResult);
-
- // Restore event sending
- aMirrArc->data()->blockSendAttributeUpdated(aWasBlocked);
- }
return aResult;
}
-void PlaneGCSSolver_Builder::adjustConstraint(ConstraintWrapperPtr theConstraint) const
+std::shared_ptr<GeomAPI_Pnt2d> PlaneGCSSolver_Builder::point(EntityWrapperPtr theEntity) const
{
- SketchSolver_ConstraintType aType = theConstraint->type();
- // Update flags and parameters in constraints
- if (aType == CONSTRAINT_PT_LINE_DISTANCE)
- adjustPtLineDistance(theConstraint);
- else if (aType == CONSTRAINT_SYMMETRIC)
- adjustMirror(theConstraint);
-}
+ if (theEntity->type() != ENTITY_POINT)
+ return std::shared_ptr<GeomAPI_Pnt2d>();
-EntityWrapperPtr PlaneGCSSolver_Builder::createFeature(
- FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& /*theSketchID*/) const
-{
- static EntityWrapperPtr aDummy;
- if (!theFeature->data()->isValid())
- return aDummy;
-
- // Sketch
- CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
- if (aSketch)
- return createSketchEntity(aSketch, theGroupID);
-
- // SketchPlugin features
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
- if (!aFeature)
- return aDummy;
-
- // Verify the feature by its kind
- const std::string& aFeatureKind = aFeature->getKind();
- // Line
- if (aFeatureKind == SketchPlugin_Line::ID())
- return createLine(theFeature, theAttributes, theGroupID);
- // Circle
- else if (aFeatureKind == SketchPlugin_Circle::ID())
- return createCircle(theFeature, theAttributes, theGroupID);
- // Arc
- else if (aFeatureKind == SketchPlugin_Arc::ID())
- return createArc(theFeature, theAttributes, theGroupID);
- // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
- else if (aFeatureKind == SketchPlugin_Point::ID() ||
- aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
- EntityWrapperPtr aSub;
- if (theAttributes.size() == 1)
- aSub = theAttributes.front();
- else {
- AttributePtr aPoint = theFeature->attribute(SketchPlugin_Point::COORD_ID());
- if (aPoint->isInitialized())
- aSub = createAttribute(aPoint, theGroupID);
- }
- if (!aSub)
- return aDummy;
-
- GCSPointPtr aSubEnt =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(aSub)->point();
- EntityWrapperPtr aNewEntity(new PlaneGCSSolver_EntityWrapper(theFeature));
- aNewEntity->setSubEntities(std::list<EntityWrapperPtr>(1, aSub));
- return aNewEntity;
- }
-
- // wrong entity
- return aDummy;
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+ const GCSPointPtr& aPoint = aPointWrapper->point();
+ return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(*aPoint->x, *aPoint->y));
}
-EntityWrapperPtr PlaneGCSSolver_Builder::createAttribute(
- AttributePtr theAttribute,
- const GroupID& theGroupID,
- const EntityID& theSketchID) const
+std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Builder::line(EntityWrapperPtr theEntity) const
{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject()) {
- // do not create features here
- return EntityWrapperPtr();
- } else
- anAttribute = aRefAttr->attr();
- }
-
- std::list<ParameterWrapperPtr> aParameters;
- EntityWrapperPtr aResult;
-
- // Point in 2D
- std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
- if (aPoint2D) {
- aParameters.push_back(::createParameter(theGroupID, aPoint2D->x(), !aPoint2D->textX().empty()));
- aParameters.push_back(::createParameter(theGroupID, aPoint2D->y(), !aPoint2D->textY().empty()));
- GCSPointPtr aGCSPoint(new GCS::Point);
- aGCSPoint->x = std::dynamic_pointer_cast<
- PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
- aGCSPoint->y = std::dynamic_pointer_cast<
- PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
- // Create entity (parameters are not filled)
- aResult = EntityWrapperPtr(new PlaneGCSSolver_PointWrapper(theAttribute, aGCSPoint));
- } else {
- // Scalar value (used for the distance entities)
- AttributeDoublePtr aScalar =
- std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
- if (aScalar)
- return createScalar(theGroupID, aScalar);
- }
-
- if (!aResult) {
- // unknown attribute type
- return EntityWrapperPtr();
- }
+ if (theEntity->type() != ENTITY_LINE)
+ return std::shared_ptr<GeomAPI_Lin2d>();
- aResult->setGroup(theGroupID);
- aResult->setParameters(aParameters);
- return aResult;
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+ return std::shared_ptr<GeomAPI_Lin2d>(
+ new GeomAPI_Lin2d(*(aLine->p1.x), *(aLine->p1.y), *(aLine->p2.x), *(aLine->p2.y)));
}
-ParameterWrapperPtr PlaneGCSSolver_Builder::createParameter(
- const GroupID& theGroupID, double theValue) const
+std::shared_ptr<GeomAPI_Lin2d> PlaneGCSSolver_Builder::line(FeaturePtr theFeature) const
{
- return ::createParameter(theGroupID, theValue);
-}
+ if (theFeature->getKind() != SketchPlugin_Line::ID())
+ return std::shared_ptr<GeomAPI_Lin2d>();
+ AttributePoint2DPtr aStart = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::START_ID()));
+ AttributePoint2DPtr aEnd = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ theFeature->attribute(SketchPlugin_Line::END_ID()));
-EntityWrapperPtr PlaneGCSSolver_Builder::createSketchEntity(
- CompositeFeaturePtr theSketch,
- const GroupID& theGroupID) const
-{
- DataPtr aSketchData = theSketch->data();
- if (!aSketchData || !aSketchData->isValid())
- return EntityWrapperPtr(); // the sketch is incorrect
-
- // Create dummy wrapper representing workplane
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> aSketchEnt(
- new PlaneGCSSolver_EntityWrapper(FeaturePtr(theSketch)));
- aSketchEnt->setGroup(theGroupID);
- aSketchEnt->setId(EID_SKETCH);
- return aSketchEnt;
+ return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aStart->pnt(), aEnd->pnt()));
}
// ================ Auxiliary functions ==========================
-ParameterWrapperPtr createParameter(
- const GroupID& theGroup, const double theValue, const bool theExpr)
-{
- double* aParam = new double(theValue);
- ParameterWrapperPtr aWrapper(new PlaneGCSSolver_ParameterWrapper(aParam));
- aWrapper->setGroup(theGroup);
- aWrapper->setIsParametric(theExpr);
- return aWrapper;
-}
-
-ParameterWrapperPtr createParamAngle(const GroupID& theGroup, const double& theValue)
-{
- double* aParam = new double(theValue);
- ParameterWrapperPtr aWrapper(new PlaneGCSSolver_AngleWrapper(aParam));
- aWrapper->setGroup(theGroup);
- return aWrapper;
-}
-
-std::shared_ptr<PlaneGCSSolver_ScalarWrapper> createScalar(
- const GroupID& theGroupID,
- AttributeDoublePtr theDoubleAttr)
-{
- ParameterWrapperPtr aParam =
- createParameter(theGroupID, theDoubleAttr ? theDoubleAttr->value() : 0.0);
- return std::shared_ptr<PlaneGCSSolver_ScalarWrapper>(
- new PlaneGCSSolver_ScalarWrapper(theDoubleAttr, aParam));
-}
-
-EntityWrapperPtr createLine(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID)
-{
- EntityWrapperPtr aNewEntity;
- std::list<EntityWrapperPtr> aSubs;
-
- AttributePtr aStart = theFeature->attribute(SketchPlugin_Line::START_ID());
- AttributePtr aEnd = theFeature->attribute(SketchPlugin_Line::END_ID());
- if (!aStart->isInitialized() || !aEnd->isInitialized())
- return aNewEntity;
-
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartEnt, aEndEnt;
- std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
- for (; anIt != theAttributes.end(); ++anIt) {
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
- if (!aWrapper)
- continue;
- if (aWrapper->isBase(aStart))
- aStartEnt = aWrapper;
- else if (aWrapper->isBase(aEnd))
- aEndEnt = aWrapper;
- }
- if (!aStartEnt || !aEndEnt)
- return aNewEntity;
-
- aSubs.push_back(aStartEnt);
- aSubs.push_back(aEndEnt);
-
- std::shared_ptr<GCS::Line> aLine(new GCS::Line);
- aLine->p1 = *(aStartEnt->point());
- aLine->p2 = *(aEndEnt->point());
-
- aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aLine));
- // sub-entities should not change their groups, therefore they are added later
- aNewEntity->setGroup(theGroupID);
- aNewEntity->setSubEntities(aSubs);
- return aNewEntity;
-}
-
-EntityWrapperPtr createCircle(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID)
-{
- EntityWrapperPtr aNewEntity;
- std::list<EntityWrapperPtr> aSubs;
-
- AttributePtr aCenter = theFeature->attribute(SketchPlugin_Circle::CENTER_ID());
- AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
- if (!aCenter->isInitialized() || !aRadius->isInitialized())
- return aNewEntity;
-
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt;
- std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aRadiusEnt;
- std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
- for (; anIt != theAttributes.end(); ++anIt) {
- if ((*anIt)->isBase(aCenter))
- aCenterEnt = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
- else if ((*anIt)->isBase(aRadius))
- aRadiusEnt = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*anIt);
- }
- if (!aCenterEnt || !aRadiusEnt)
- return aNewEntity;
-
- aSubs.push_back(aCenterEnt);
- aSubs.push_back(aRadiusEnt);
-
- std::shared_ptr<GCS::Circle> aCircle(new GCS::Circle);
- aCircle->center = *(aCenterEnt->point());
- aCircle->rad = aRadiusEnt->scalar();
-
- aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, aCircle));
- // sub-entities should not change their groups, therefore they are added later
- aNewEntity->setGroup(theGroupID);
- aNewEntity->setSubEntities(aSubs);
- return aNewEntity;
-}
-
-EntityWrapperPtr createArc(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID)
-{
- EntityWrapperPtr aNewEntity;
- std::list<EntityWrapperPtr> aSubs;
-
- AttributePtr aCenter = theFeature->attribute(SketchPlugin_Arc::CENTER_ID());
- AttributePtr aStart = theFeature->attribute(SketchPlugin_Arc::START_ID());
- AttributePtr aEnd = theFeature->attribute(SketchPlugin_Arc::END_ID());
- if (!aCenter->isInitialized() || !aStart->isInitialized() || !aEnd->isInitialized())
- return aNewEntity;
-
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aCenterEnt, aStartEnt, aEndEnt;
- std::list<EntityWrapperPtr>::const_iterator anIt = theAttributes.begin();
- for (; anIt != theAttributes.end(); ++anIt) {
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aWrapper =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anIt);
- if (!aWrapper)
- continue;
- if (aWrapper->isBase(aCenter))
- aCenterEnt = aWrapper;
- else if (aWrapper->isBase(aStart))
- aStartEnt = aWrapper;
- else if (aWrapper->isBase(aEnd))
- aEndEnt = aWrapper;
- }
- if (!aCenterEnt || !aStartEnt || !aEndEnt)
- return aNewEntity;
-
- std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aStartAng, aEndAng, aRadius;
- aStartAng = createScalar(theGroupID);
- aEndAng = createScalar(theGroupID);
- aRadius = createScalar(theGroupID);
-
- aSubs.push_back(aCenterEnt);
- aSubs.push_back(aStartEnt);
- aSubs.push_back(aEndEnt);
- aSubs.push_back(aStartAng);
- aSubs.push_back(aEndAng);
- aSubs.push_back(aRadius);
-
- std::shared_ptr<GCS::Arc> anArc(new GCS::Arc);
- anArc->center = *(aCenterEnt->point());
- anArc->start = *(aStartEnt->point());
- anArc->end = *(aEndEnt->point());
- anArc->startAngle = aStartAng->scalar();
- anArc->endAngle = aEndAng->scalar();
- anArc->rad = aRadius->scalar();
-
- aNewEntity = EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(theFeature, anArc));
- // sub-entities should not change their groups, therefore they are added later
- aNewEntity->setGroup(theGroupID);
- aNewEntity->setSubEntities(aSubs);
- return aNewEntity;
-}
-
-
-
ConstraintWrapperPtr createConstraintCoincidence(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
{
+ GCSPointPtr aPoint1 = thePoint1->point();
+ GCSPointPtr aPoint2 = thePoint2->point();
+
// Create equality constraint for corresponding attributes of the points
std::list<GCSConstraintPtr> aConstrList;
- std::list<ParameterWrapperPtr>::const_iterator anIt1 = thePoint1->parameters().begin();
- std::list<ParameterWrapperPtr>::const_iterator anIt2 = thePoint2->parameters().begin();
- for (; anIt1 != thePoint1->parameters().end(); ++anIt1, ++anIt2) {
- if (*anIt1 == *anIt2)
- continue; // points use same parameters, no need additional constraints
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam1 =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt1);
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam2 =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*anIt2);
- aConstrList.push_back(
- GCSConstraintPtr(new GCS::ConstraintEqual(aParam1->parameter(), aParam2->parameter())));
- }
+ aConstrList.push_back(
+ GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->x, aPoint2->x)));
+ aConstrList.push_back(
+ GCSConstraintPtr(new GCS::ConstraintEqual(aPoint1->y, aPoint2->y)));
- ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
- theConstraint, aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, thePoint1);
- aSubs.push_back(thePoint2);
- aResult->setEntities(aSubs);
- return aResult;
+ return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(
+ aConstrList, CONSTRAINT_PT_PT_COINCIDENT));
}
ConstraintWrapperPtr createConstraintPointOnEntity(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
return ConstraintWrapperPtr();
}
- ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
- theConstraint, aNewConstr, theType));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, thePoint);
- aSubs.push_back(theEntity);
- aResult->setEntities(aSubs);
- return aResult;
-}
-
-// calculate length of the line
-static inline double lineLength(const GCS::Line& theLine)
-{
- double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
- return sqrt(aDir[0] * aDir[0] + aDir[1] * aDir[1]);
-}
-
-// check the point is on the line
-static inline bool isPointOnLine(const GCS::Point& thePoint, const GCS::Line& theLine)
-{
- double aDir[2] = {*(theLine.p2.x) - *(theLine.p1.x), *(theLine.p2.y) - *(theLine.p1.y)};
- double aVec[2] = {*(thePoint.x) - *(theLine.p1.x), *(thePoint.y) - *(theLine.p1.y)};
- double aCross = aVec[0] * aDir[1] - aVec[1] * aDir[0];
- return fabs(aCross) < tolerance;
+ return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
}
ConstraintWrapperPtr createConstraintMiddlePoint(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
{
return ConstraintWrapperPtr();
std::list<GCSConstraintPtr> aConstrList;
+ aConstrList.push_back(
+ GCSConstraintPtr(new GCS::ConstraintPointOnPerpBisector(*aPoint, aLine->p1, aLine->p2)));
aConstrList.push_back(GCSConstraintPtr(new GCS::ConstraintPointOnLine(*aPoint, *aLine)));
- double aDist = lineLength(*aLine);
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aDistance =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(
- createParameter(theGroupID, aDist * 0.5));
- aConstrList.push_back(GCSConstraintPtr(
- new GCS::ConstraintP2PDistance(*aPoint, aLine->p1, aDistance->parameter())));
- aConstrList.push_back(GCSConstraintPtr(
- new GCS::ConstraintP2PDistance(*aPoint, aLine->p2, aDistance->parameter())));
-
- // Workaround to avoid conflicting constraints when the point is already placed on line
- if (thePoint->group() != GID_UNKNOWN && isPointOnLine(*aPoint, *aLine)) {
- std::shared_ptr<GeomDataAPI_Point2D> aCoord =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(thePoint->baseAttribute());
- if (aCoord) {
- *(aPoint->x) = (*(aLine->p1.x) + *(aLine->p2.x)) * 0.5;
- *(aPoint->y) = (*(aLine->p1.y) + *(aLine->p2.y)) * 0.5;
- aCoord->setValue(*(aPoint->x), *(aPoint->y));
- }
- }
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(new PlaneGCSSolver_ConstraintWrapper(
- theConstraint, aConstrList, CONSTRAINT_MIDDLE_POINT));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, thePoint);
- aSubs.push_back(theEntity);
- aResult->setEntities(aSubs);
- aResult->setValueParameter(aDistance);
- return aResult;
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_MIDDLE_POINT));
}
ConstraintWrapperPtr createConstraintDistancePointPoint(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
- std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
- std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint1,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint2)
{
GCSConstraintPtr aNewConstr(new GCS::ConstraintP2PDistance(
- *(thePoint1->point()), *(thePoint2->point()), theValue->parameter()));
-
+ *(thePoint1->point()), *(thePoint2->point()), theValue->scalar()));
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, thePoint1);
- aSubs.push_back(thePoint2);
- aResult->setEntities(aSubs);
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_PT_DISTANCE));
aResult->setValueParameter(theValue);
return aResult;
}
ConstraintWrapperPtr createConstraintDistancePointLine(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
- std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> thePoint,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
{
std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(theEntity->entity());
GCSConstraintPtr aNewConstr(new GCS::ConstraintP2LDistance(
- *(thePoint->point()), *(aLine), theValue->parameter()));
-
+ *(thePoint->point()), *(aLine), theValue->scalar()));
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, thePoint);
- aSubs.push_back(theEntity);
- aResult->setEntities(aSubs);
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PT_LINE_DISTANCE));
aResult->setValueParameter(theValue);
return aResult;
}
ConstraintWrapperPtr createConstraintRadius(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
{
std::shared_ptr<GCS::Circle> aCircle =
std::dynamic_pointer_cast<GCS::Circle>(theEntity->entity());
- GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->parameter()));
-
+ GCSConstraintPtr aNewConstr(new GCS::ConstraintEqual(aCircle->rad, theValue->scalar()));
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_RADIUS));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity);
- aResult->setEntities(aSubs);
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_RADIUS));
aResult->setValueParameter(theValue);
return aResult;
}
ConstraintWrapperPtr createConstraintAngle(
ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theValue,
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theValue,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
{
GCS::Point aLine2Pt2 = isLine2Rev ? aLine2->p1 : aLine2->p2;
GCSConstraintPtr aNewConstr(new GCS::ConstraintL2LAngle(
- aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->parameter()));
+ aLine1Pt1, aLine1Pt2, aLine2Pt1, aLine2Pt2, theValue->scalar()));
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_ANGLE));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aResult->setEntities(aSubs);
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_ANGLE));
aResult->setValueParameter(theValue);
return aResult;
}
ConstraintWrapperPtr createConstraintHorizVert(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity)
{
else
aNewConstr = GCSConstraintPtr(new GCS::ConstraintEqual(aLine->p1.x, aLine->p2.x));
- ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
- theConstraint, aNewConstr, theType));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity);
- aResult->setEntities(aSubs);
- return aResult;
+ return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
}
ConstraintWrapperPtr createConstraintCollinear(
ConstraintPtr theConstraint,
- const GroupID& theGroupID,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
{
aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p1, *aLine1)) );
aConstrList.push_back( GCSConstraintPtr(new GCS::ConstraintPointOnLine(aLine2->p2, *aLine1)) );
- ConstraintWrapperPtr aResult(new PlaneGCSSolver_ConstraintWrapper(
- theConstraint, aConstrList, CONSTRAINT_COLLINEAR));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aResult->setEntities(aSubs);
- return aResult;
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstrList, CONSTRAINT_COLLINEAR));
}
ConstraintWrapperPtr createConstraintParallel(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
{
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
GCSConstraintPtr aNewConstr(new GCS::ConstraintParallel(*(aLine1), *(aLine2)));
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PARALLEL));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aResult->setEntities(aSubs);
- return aResult;
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PARALLEL));
}
ConstraintWrapperPtr createConstraintPerpendicular(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
{
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
GCSConstraintPtr aNewConstr(new GCS::ConstraintPerpendicular(*(aLine1), *(aLine2)));
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, CONSTRAINT_PERPENDICULAR));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aResult->setEntities(aSubs);
- return aResult;
+ return ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aNewConstr, CONSTRAINT_PERPENDICULAR));
}
ConstraintWrapperPtr createConstraintEqual(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2,
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> theIntermed)
+ std::shared_ptr<PlaneGCSSolver_ScalarWrapper> theIntermed)
{
if (theType == CONSTRAINT_EQUAL_LINE_ARC)
return ConstraintWrapperPtr(); // line-arc equivalence is not supported yet
std::shared_ptr<GCS::Line> aLine2 = std::dynamic_pointer_cast<GCS::Line>(theEntity2->entity());
aConstrList.push_back(GCSConstraintPtr(
- new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->parameter())));
+ new GCS::ConstraintP2PDistance(aLine1->p1, aLine1->p2, theIntermed->scalar())));
aConstrList.push_back(GCSConstraintPtr(
- new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->parameter())));
+ new GCS::ConstraintP2PDistance(aLine2->p1, aLine2->p2, theIntermed->scalar())));
// update value of intermediate parameter
double x = *aLine1->p1.x - *aLine1->p2.x;
double y = *aLine1->p1.y - *aLine1->p2.y;
}
std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aConstrList, theType));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aResult->setEntities(aSubs);
+ new PlaneGCSSolver_ConstraintWrapper(aConstrList, theType));
if (theIntermed)
aResult->setValueParameter(theIntermed);
return aResult;
}
ConstraintWrapperPtr createConstraintTangent(
- ConstraintPtr theConstraint,
- const GroupID& theGroupID,
const SketchSolver_ConstraintType& theType,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity1,
std::shared_ptr<PlaneGCSSolver_EntityWrapper> theEntity2)
aCirc1->rad, aCirc2->rad, (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad))));
}
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aResult(
- new PlaneGCSSolver_ConstraintWrapper(theConstraint, aNewConstr, theType));
- aResult->setGroup(theGroupID);
- std::list<EntityWrapperPtr> aSubs(1, theEntity1);
- aSubs.push_back(theEntity2);
- aResult->setEntities(aSubs);
- return aResult;
-}
-
-
-
-
-
-void makeMirrorPoints(EntityWrapperPtr theOriginal,
- EntityWrapperPtr theMirrored,
- EntityWrapperPtr theMirrorLine)
-{
- BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
-
- std::shared_ptr<GeomAPI_Lin2d> aMirrorLine = aBuilder->line(theMirrorLine);
- std::shared_ptr<GeomAPI_Dir2d> aMLDir = aMirrorLine->direction();
- // orthogonal direction
- aMLDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(aMLDir->y(), -aMLDir->x()));
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(theOriginal);
- std::shared_ptr<GeomAPI_XY> aVec = aPoint->xy()->decreased(aMirrorLine->location()->xy());
- double aDist = aVec->dot(aMLDir->xy());
- aVec = aPoint->xy()->added(aMLDir->xy()->multiplied(-2.0 * aDist));
- double aCoord[2] = {aVec->x(), aVec->y()};
- std::list<ParameterWrapperPtr>::const_iterator aMIt = theMirrored->parameters().begin();
- for (int i = 0; aMIt != theMirrored->parameters().end(); ++aMIt, ++i)
- (*aMIt)->setValue(aCoord[i]);
-
- // update corresponding attribute
- AttributePtr anAttr =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMirrored)->baseAttribute();
- if (anAttr) {
- std::shared_ptr<GeomDataAPI_Point2D> aMirroredPnt =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
- aMirroredPnt->setValue(aCoord[0], aCoord[1]);
- }
-}
-
-void adjustPtLineDistance(ConstraintWrapperPtr theConstraint)
-{
- BuilderPtr aBuilder = PlaneGCSSolver_Builder::getInstance();
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoint;
- std::shared_ptr<GeomAPI_Lin2d> aLine;
- std::list<EntityWrapperPtr> aSubs = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (; aSIt != aSubs.end(); ++aSIt) {
- if ((*aSIt)->type() == ENTITY_POINT)
- aPoint = aBuilder->point(*aSIt);
- else if ((*aSIt)->type() == ENTITY_LINE)
- aLine = aBuilder->line(*aSIt);
- }
-
- std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
- std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
- if (aPtLineVec->cross(aLineVec) * theConstraint->value() < 0.0)
- theConstraint->setValue(theConstraint->value() * (-1.0));
-}
-
-void adjustMirror(ConstraintWrapperPtr theConstraint)
-{
- std::vector<EntityWrapperPtr> aPoints;
- EntityWrapperPtr aMirrorLine;
-
- const std::list<EntityWrapperPtr>& aSubs = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (; anIt != aSubs.end(); ++anIt) {
- if ((*anIt)->type() == ENTITY_POINT)
- aPoints.push_back(*anIt);
- else if ((*anIt)->type() == ENTITY_LINE)
- aMirrorLine = *anIt;
- }
-
- if (aPoints.size() == 2)
- makeMirrorPoints(aPoints[0], aPoints[1], aMirrorLine);
-
- // update scales of constraints
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCSConstraint =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
- std::list<GCSConstraintPtr>::const_iterator aCIt = aGCSConstraint->constraints().begin();
- for (; aCIt != aGCSConstraint->constraints().end(); ++aCIt)
- (*aCIt)->rescale();
+ return ConstraintWrapperPtr(new PlaneGCSSolver_ConstraintWrapper(aNewConstr, theType));
}
bool PlaneGCSSolver_Builder::isArcArcTangencyInternal(
return (aDist < *(aCirc1->rad) || aDist < *(aCirc2->rad));
}
-
*/
class PlaneGCSSolver_Builder : public SketchSolver_Builder
{
-private:
/// Default constructor
PlaneGCSSolver_Builder() {}
static BuilderPtr getInstance();
/// \brief Creates a storage specific for used solver
- virtual StoragePtr createStorage(const GroupID& theGroup) const;
+ virtual StoragePtr createStorage(const SolverPtr& theSolver) const override;
/// \brief Creates specific solver
- virtual SolverPtr createSolver() const;
+ virtual SolverPtr createSolver() const override;
- /// \brief Creates new constraint(s) using given parameters
+ /// \brief Creates new constraint using given parameters
/// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
/// \param theType [in] type of constraint
/// \param theValue [in] numeric characteristic of constraint
/// (e.g. distance or radius) if applicable
/// \param theEntity2 [in] second attribute of constraint
/// \param theEntity3 [in] third attribute of constraint
/// \param theEntity4 [in] fourth attribute of constraint
- /// \return Created list of wrappers of constraints applicable for specific solver.
- /// Most of constraint types lead to single constraint, but there are some kind of
- /// constraints (e.g. mirror), which may produce couple of constraints.
- virtual std::list<ConstraintWrapperPtr>
+ /// \return Created wrapper of constraints applicable for specific solver.
+ virtual ConstraintWrapperPtr
createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
const SketchSolver_ConstraintType& theType,
- const double& theValue,
+ const EntityWrapperPtr& theValue,
const EntityWrapperPtr& theEntity1,
const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
- const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const;
+ const EntityWrapperPtr& theEntity4 = EntityWrapperPtr()) const override;
/// \brief Creates new multi-translation or multi-rotation constraint
/// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
/// \param theType [in] type of constraint
/// \param theValue [in] numeric characteristic of constraint (angle for multi-rotation)
/// if applicable
/// \param thePoint1 [in] center for multi-rotation or start point for multi-translation
/// \param thePoint2 [in] end point for multi-translation (empty for multi-rotation)
/// \param theTrsfEnt [in] list of transformed entities
- virtual std::list<ConstraintWrapperPtr>
+ virtual ConstraintWrapperPtr
createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
const SketchSolver_ConstraintType& theType,
- const double& theValue,
+ const EntityWrapperPtr& theValue,
const bool theFullValue,
const EntityWrapperPtr& thePoint1,
const EntityWrapperPtr& thePoint2,
- const std::list<EntityWrapperPtr>& theTrsfEnt) const;
+ const std::list<EntityWrapperPtr>& theTrsfEnt) const override;
- /// \brief Update flags for several kinds of constraints
- virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const;
+ /// \brief Convert entity to point
+ /// \return empty pointer if the entity is not a point
+ virtual std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const override;
+ /// \brief Convert entity to line
+ /// \return empty pointer if the entity is not a line
+ virtual std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const override;
- /// \brief Creates a feature using list of already created attributes
- /// \param theFeature [in] feature to create
- /// \param theAttributes [in] attributes of the feature
- /// \param theGroupID [in] group the feature belongs to
- /// \param theSketchID [in] sketch the feature belongs to
- /// \return Created wrapper of the feature applicable for specific solver
- virtual EntityWrapperPtr createFeature(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID = EID_UNKNOWN) const;
-
- /// \brief Creates an attribute
- /// \param theAttribute [in] attribute to create
- /// \param theGroup [in] group the attribute belongs to
- /// \param theSketchID [in] sketch the attribute belongs to
- /// \return Created wrapper of the attribute applicable for specific solver
- virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute,
- const GroupID& theGroup,
- const EntityID& theSketchID = EID_UNKNOWN) const;
-
- /// \brief Create a parameter
- /// \param theGroupID [in] group the parameter belongs to
- /// \param theValue [in] value of the parameter
- /// \return Created wrapper for parameter
- ParameterWrapperPtr createParameter(const GroupID& theGroupID, double theValue = 0.0) const;
+ /// \brief Convert entity to line
+ /// \return empty pointer if the entity is not a line
+ virtual std::shared_ptr<GeomAPI_Lin2d> line(FeaturePtr theFeature) const override;
/// \brief Check if two connected arcs have centers
/// in same direction relatively to connection point
- virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1, EntityWrapperPtr theArc2) const;
-
-private:
- /// \brief Create necessary constraints to make two object symmetric relatively a given line
- std::list<ConstraintWrapperPtr> createMirror(ConstraintPtr theConstraint,
- const GroupID& theGroupID,
- const EntityID& theSketchID,
- const EntityWrapperPtr& theEntity1,
- const EntityWrapperPtr& theEntity2,
- const EntityWrapperPtr& theMirrorLine) const;
-
- /// \brief Converts sketch parameters to the entity applicable for the solver.
- /// \param theSketch [in] the element to be converted
- /// \param theGroupID [in] group where the sketch should be created
- /// \return Entity respective the sketch or empty pointer, it the sketch has incorrect attributes
- EntityWrapperPtr createSketchEntity(CompositeFeaturePtr theSketch,
- const GroupID& theGroupID) const;
-
-private:
- static BuilderPtr mySelf;
+ virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
+ EntityWrapperPtr theArc2) const override;
};
#endif
#include <PlaneGCSSolver_ConstraintWrapper.h>
-#include <math.h>
-
PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
- const ConstraintPtr& theOriginal,
const GCSConstraintPtr& theConstraint,
const SketchSolver_ConstraintType& theType)
: myGCSConstraints(1, theConstraint),
- myType(theType),
- myID(CID_UNKNOWN)
+ myType(theType)
{
- myBaseConstraint = theOriginal;
- myValue = 0.0;
+ myID = CID_UNKNOWN;
}
PlaneGCSSolver_ConstraintWrapper::PlaneGCSSolver_ConstraintWrapper(
- const ConstraintPtr& theOriginal,
const std::list<GCSConstraintPtr>& theConstraints,
const SketchSolver_ConstraintType& theType)
: myGCSConstraints(theConstraints),
- myType(theType),
- myID(CID_UNKNOWN)
+ myType(theType)
{
- myBaseConstraint = theOriginal;
- myValue = 0.0;
+ myID = CID_UNKNOWN;
}
void PlaneGCSSolver_ConstraintWrapper::setId(const ConstraintID& theID)
(*anIt)->setTag((int)theID);
}
-void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ParameterWrapperPtr& theValue)
+void PlaneGCSSolver_ConstraintWrapper::setValueParameter(const ScalarWrapperPtr& theValue)
{
myValueParam = theValue;
- myValue = myValueParam->value();
}
void PlaneGCSSolver_ConstraintWrapper::setValue(const double& theValue)
{
- myValue = theValue;
myValueParam->setValue(theValue);
}
-
-void PlaneGCSSolver_ConstraintWrapper::setGroup(const GroupID& theGroup)
-{
- myGroup = theGroup;
- std::list<EntityWrapperPtr>::iterator aSubsIt = myConstrained.begin();
- for (; aSubsIt != myConstrained.end(); ++aSubsIt)
- (*aSubsIt)->setGroup(theGroup);
-}
-
-bool PlaneGCSSolver_ConstraintWrapper::isUsed(FeaturePtr theFeature) const
-{
- std::list<EntityWrapperPtr>::const_iterator anIt = myConstrained.begin();
- for (; anIt != myConstrained.end(); ++anIt)
- if ((*anIt)->isUsed(theFeature))
- return true;
- return false;
-}
-
-bool PlaneGCSSolver_ConstraintWrapper::isUsed(AttributePtr theAttribute) const
-{
- std::list<EntityWrapperPtr>::const_iterator anIt = myConstrained.begin();
- for (; anIt != myConstrained.end(); ++anIt)
- if ((*anIt)->isUsed(theAttribute))
- return true;
- return false;
-}
-
-bool PlaneGCSSolver_ConstraintWrapper::isEqual(const ConstraintWrapperPtr& theOther)
+double PlaneGCSSolver_ConstraintWrapper::value() const
{
- if (type() != theOther->type())
- return false;
-
- // Verify equality of values
- if (fabs(myValue - theOther->value()) > tolerance)
- return false;
-
- // Verify equality of entities
- const std::list<EntityWrapperPtr>& anOtherSubs = theOther->entities();
- if (myConstrained.size() != anOtherSubs.size())
- return false;
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = myConstrained.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != myConstrained.end(); ++aMySubsIt, ++anOtherSubsIt)
- if (!(*aMySubsIt)->isEqual(*anOtherSubsIt))
- return false;
- return true;
-}
-
-bool PlaneGCSSolver_ConstraintWrapper::update(const ConstraintWrapperPtr& theOther)
-{
- bool isUpdated = false;
-
- std::list<EntityWrapperPtr> aMySubs = entities();
- std::list<EntityWrapperPtr> anOtherSubs = theOther->entities();
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = aMySubs.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != aMySubs.end() && anOtherSubsIt != anOtherSubs.end();
- ++aMySubsIt, ++anOtherSubsIt)
- isUpdated = (*aMySubsIt)->update(*anOtherSubsIt) || isUpdated;
-
- if (fabs(value() - theOther->value()) > tolerance) {
- myValue = theOther->value();
- isUpdated = true;
- }
- return isUpdated;
+ return myValueParam->value();
}
#include <PlaneGCSSolver_Defs.h>
#include <PlaneGCSSolver_Solver.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
#include <SketchSolver_IConstraintWrapper.h>
/**
- * Wrapper providing operations with SovleSpace constraints.
+ * Wrapper providing operations with PlaneGCS constraints.
*/
class PlaneGCSSolver_ConstraintWrapper : public SketchSolver_IConstraintWrapper
{
public:
- PlaneGCSSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
- const GCSConstraintPtr& theConstraint,
+ PlaneGCSSolver_ConstraintWrapper(const GCSConstraintPtr& theConstraint,
const SketchSolver_ConstraintType& theType);
- PlaneGCSSolver_ConstraintWrapper(const ConstraintPtr& theOriginal,
- const std::list<GCSConstraintPtr>& theConstraints,
+ PlaneGCSSolver_ConstraintWrapper(const std::list<GCSConstraintPtr>& theConstraints,
const SketchSolver_ConstraintType& theType);
/// \brief Return list of constraints
void setConstraints(const std::list<GCSConstraintPtr>& theConstraints)
{ myGCSConstraints = theConstraints; }
- /// \brief Return ID of current entity
- virtual ConstraintID id() const
- { return myID; }
/// \brief Change constraint ID
- void setId( const ConstraintID& theID);
-
- /// \brief Change group for the constraint
- virtual void setGroup(const GroupID& theGroup);
- /// \brief Return identifier of the group the constraint belongs to
- virtual GroupID group() const
- { return myGroup; }
+ virtual void setId(const ConstraintID& theID);
/// \brief Return type of current entity
virtual SketchSolver_ConstraintType type() const
/// \brief Assign numeric parameter of constraint
virtual void setValue(const double& theValue);
+ /// \brief Return numeric parameter of constraint
+ virtual double value() const;
/// \brief Change parameter representing the value of constraint
- void setValueParameter(const ParameterWrapperPtr& theValue);
+ void setValueParameter(const ScalarWrapperPtr& theValue);
/// \brief Return parametric representation of constraint value
- const ParameterWrapperPtr& valueParameter() const
+ const ScalarWrapperPtr& valueParameter() const
{ return myValueParam; }
- /// \brief Verify the feature is used in the constraint
- virtual bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used in the constraint
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Compare current constraint with other
- virtual bool isEqual(const ConstraintWrapperPtr& theOther);
-
- /// \brief Update values of parameters of this constraint by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther);
-
private:
- ConstraintID myID;
- GroupID myGroup;
SketchSolver_ConstraintType myType;
- ParameterWrapperPtr myValueParam;
+ ScalarWrapperPtr myValueParam;
std::list<GCSConstraintPtr> myGCSConstraints;
};
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_EntityBuilder.h
+// Created: 14 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_EntityBuilder_H_
+#define PlaneGCSSolver_EntityBuilder_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_Storage.h>
+
+/** \class PlaneGCSSolver_EntityBuilder
+ * \ingroup Plugins
+ * \brief API to convert data model entity to the entity applicable for PlaneGCS solver
+ */
+class PlaneGCSSolver_EntityBuilder
+{
+public:
+ /// \brief Create entity in the given storage.
+ /// If the storage is empty, the entity should not be changed
+ /// while constraint solving. So, it is created out of the storage.
+ PlaneGCSSolver_EntityBuilder(PlaneGCSSolver_Storage* theStorage = 0)
+ : myStorage(theStorage)
+ {}
+
+ virtual ~PlaneGCSSolver_EntityBuilder() {}
+
+ /// \brief Converts an attribute to the solver's entity.
+ /// Double attributes and 2D points are supported only.
+ /// \param theAttribute [in] attribute to create
+ /// \return Created wrapper of the attribute applicable for specific solver
+ virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute) = 0;
+
+ /// \brief Converts SketchPlugin's feature to the solver's entity.
+ /// Result if based on the list of already converted attributes.
+ /// \param theFeature [in] feature to create
+ virtual EntityWrapperPtr createFeature(FeaturePtr) = 0;
+
+ /// \brief Return list of constraints necessary to fix feature's extra DoF
+ virtual const std::list<GCSConstraintPtr>& constraints() const = 0;
+
+protected:
+ PlaneGCSSolver_Storage* myStorage;
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_EntityDestroyer.cpp
+// Created: 10 Feb 2017
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_EntityDestroyer.h>
+
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+
+static void destroyScalar(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+ ScalarWrapperPtr aScalar = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
+ theParams.insert(aScalar->scalar());
+}
+
+static void destroyPoint(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
+ theParams.insert(aPoint->point()->x);
+ theParams.insert(aPoint->point()->y);
+}
+
+static void destroyLine(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+ theParams.insert(aLine->p1.x);
+ theParams.insert(aLine->p1.y);
+ theParams.insert(aLine->p2.x);
+ theParams.insert(aLine->p2.y);
+}
+
+static void destroyCircle(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+ std::shared_ptr<GCS::Circle> aCirc = std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
+ theParams.insert(aCirc->center.x);
+ theParams.insert(aCirc->center.y);
+ theParams.insert(aCirc->rad);
+}
+
+static void destroyArc(const EntityWrapperPtr& theEntity, GCS::SET_pD& theParams)
+{
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
+ theParams.insert(anArc->center.x);
+ theParams.insert(anArc->center.y);
+ theParams.insert(anArc->start.x);
+ theParams.insert(anArc->start.y);
+ theParams.insert(anArc->end.x);
+ theParams.insert(anArc->end.y);
+ theParams.insert(anArc->startAngle);
+ theParams.insert(anArc->endAngle);
+ theParams.insert(anArc->rad);
+}
+
+void PlaneGCSSolver_EntityDestroyer::remove(const EntityWrapperPtr& theEntity)
+{
+ GCS::SET_pD& aParamSet = theEntity->isExternal() ? myParamsOutOfStorage : myParams;
+
+ switch (theEntity->type()) {
+ case ENTITY_SCALAR:
+ case ENTITY_ANGLE:
+ destroyScalar(theEntity, aParamSet);
+ break;
+ case ENTITY_POINT:
+ destroyPoint(theEntity, aParamSet);
+ break;
+ case ENTITY_LINE:
+ destroyLine(theEntity, aParamSet);
+ break;
+ case ENTITY_CIRCLE:
+ destroyCircle(theEntity, aParamSet);
+ break;
+ case ENTITY_ARC:
+ destroyArc(theEntity, aParamSet);
+ break;
+ default: break;
+ }
+}
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_EntityDestroyer.h
+// Created: 10 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_EntityDestroyer_H_
+#define PlaneGCSSolver_EntityDestroyer_H_
+
+#include <PlaneGCSSolver_Defs.h>
+#include <PlaneGCSSolver_Storage.h>
+
+/** \class PlaneGCSSolver_EntityDestroyer
+ * \ingroup Plugins
+ * \brief Collect entities of PlaneGCS solver which should be removed
+ */
+class PlaneGCSSolver_EntityDestroyer
+{
+public:
+ PlaneGCSSolver_EntityDestroyer() {}
+
+ /// \brief Add entity to remove. Its parameters are stored for further remove from the storage.
+ void remove(const EntityWrapperPtr& theEntity);
+
+ /// \brief Return parameters to remove
+ const GCS::SET_pD& parametersToRemove()
+ { return myParams; }
+
+private:
+ GCS::SET_pD myParams; ///< set of parameters to be removed
+ GCS::SET_pD myParamsOutOfStorage; ///< set of parameters not kept in the storage
+};
+
+#endif
// Author: Artem ZHIDKOV
#include <PlaneGCSSolver_EntityWrapper.h>
-#include <SketchPlugin_Point.h>
-#include <SketchPlugin_IntersectionPoint.h>
-#include <SketchPlugin_Sketch.h>
-PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper(
- const FeaturePtr theFeature, const GCSCurvePtr theEntity)
- : myEntity(theEntity),
- myID(EID_UNKNOWN)
+PlaneGCSSolver_EntityWrapper::PlaneGCSSolver_EntityWrapper(const GCSCurvePtr theEntity)
+ : myEntity(theEntity)
{
- myBaseFeature = theFeature;
-
std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(myEntity);
if (aLine) myType = ENTITY_LINE;
else {
if (aCircle) myType = ENTITY_CIRCLE;
}
}
-
- // empty entity, probably this is a SketchPlugin_Point or SketchPlugin_Sketch
- if (theFeature->getKind() == SketchPlugin_Point::ID() ||
- theFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
- myType = ENTITY_POINT;
- else if (theFeature->getKind() == SketchPlugin_Sketch::ID())
- myType = ENTITY_SKETCH;
-}
-
-void PlaneGCSSolver_EntityWrapper::setGroup(const GroupID& theGroup)
-{
- myGroup = theGroup;
- std::list<EntityWrapperPtr>::iterator aSubsIt = mySubEntities.begin();
- for (; aSubsIt != mySubEntities.end(); ++aSubsIt)
- (*aSubsIt)->setGroup(theGroup);
- std::list<ParameterWrapperPtr>::iterator aPIt = myParameters.begin();
- for (; aPIt != myParameters.end(); ++aPIt)
- (*aPIt)->setGroup(theGroup);
-}
-
-bool PlaneGCSSolver_EntityWrapper::isUsed(FeaturePtr theFeature) const
-{
- if (isBase(theFeature))
- return true;
-
- std::list<EntityWrapperPtr>::const_iterator anIt = mySubEntities.begin();
- for (; anIt != mySubEntities.end(); ++anIt)
- if ((*anIt)->isUsed(theFeature))
- return true;
- return false;
-}
-
-bool PlaneGCSSolver_EntityWrapper::isUsed(AttributePtr theAttribute) const
-{
- if (isBase(theAttribute))
- return true;
-
- std::list<EntityWrapperPtr>::const_iterator anIt = mySubEntities.begin();
- for (; anIt != mySubEntities.end(); ++anIt)
- if ((*anIt)->isUsed(theAttribute))
- return true;
- return false;
-}
-
-bool PlaneGCSSolver_EntityWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
- if (type() != theOther->type())
- return false;
-
- // Verify Equality of sub-entities
- const std::list<EntityWrapperPtr>& anOtherSubs = theOther->subEntities();
- if (mySubEntities.size() != anOtherSubs.size())
- return false;
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = mySubEntities.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != mySubEntities.end(); ++aMySubsIt, ++anOtherSubsIt)
- if (!(*aMySubsIt)->isEqual(*anOtherSubsIt))
- return false;
-
- // Verify equality of parameters
- const std::list<ParameterWrapperPtr>& anOtherParams = theOther->parameters();
- if (myParameters.size() != anOtherParams.size())
- return false;
- std::list<ParameterWrapperPtr>::const_iterator aMyIt = myParameters.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherIt = anOtherParams.begin();
- for (; aMyIt != myParameters.end(); ++aMyIt, ++anOtherIt)
- if (!(*aMyIt)->isEqual(*anOtherIt))
- return false;
- return true;
-}
-
-bool PlaneGCSSolver_EntityWrapper::update(const EntityWrapperPtr& theOther)
-{
- bool isUpdated = false;
-
- std::list<EntityWrapperPtr> aMySubs = subEntities();
- std::list<EntityWrapperPtr> anOtherSubs = theOther->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aMySubsIt = aMySubs.begin();
- std::list<EntityWrapperPtr>::const_iterator anOtherSubsIt = anOtherSubs.begin();
- for (; aMySubsIt != aMySubs.end() && anOtherSubsIt != anOtherSubs.end();
- ++aMySubsIt, ++anOtherSubsIt)
- isUpdated = (*aMySubsIt)->update(*anOtherSubsIt) || isUpdated;
-
- std::list<ParameterWrapperPtr> aMyParams = parameters();
- std::list<ParameterWrapperPtr> anOtherParams = theOther->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aMyParIt = aMyParams.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherParIt = anOtherParams.begin();
- for (; aMyParIt != aMyParams.end() && anOtherParIt != anOtherParams.end();
- ++aMyParIt, ++anOtherParIt)
- isUpdated = (*aMyParIt)->update(*anOtherParIt);
- return isUpdated;
}
#include <SketchSolver_IEntityWrapper.h>
/**
- * Wrapper providing operations with PlaneGCS entities.
+ * Wrapper providing operations with PlaneGCS entities (lines, circles and arcs).
*/
class PlaneGCSSolver_EntityWrapper : public SketchSolver_IEntityWrapper
{
public:
- PlaneGCSSolver_EntityWrapper(const FeaturePtr theFeature,
- const GCSCurvePtr theEntity = GCSCurvePtr());
+ PlaneGCSSolver_EntityWrapper(const GCSCurvePtr theEntity);
/// \brief Return PlaneGCS geometric entity
const GCSCurvePtr& entity() const
GCSCurvePtr& changeEntity()
{ return myEntity; }
- /// \brief Return ID of current entity
- virtual EntityID id() const
- { return myID; }
- /// \brief Change ID of the entity
- void setId(EntityID theID)
- { myID = theID; }
-
- /// \brief Change group for the entity
- virtual void setGroup(const GroupID& theGroup);
- /// \brief Return identifier of the group the entity belongs to
- virtual GroupID group() const
- { return myGroup; }
-
/// \brief Return type of current entity
virtual SketchSolver_EntityType type() const
{ return myType; }
- /// \brief Verify the feature is used in the entity
- virtual bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used in the entity
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Compare current entity with other
- virtual bool isEqual(const EntityWrapperPtr& theOther);
-
- /// \brief Update values of parameters of this entity by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const EntityWrapperPtr& theOther);
-
private:
- EntityID myID;
- GroupID myGroup;
SketchSolver_EntityType myType;
GCSCurvePtr myEntity;
};
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_AttributeBuilder.cpp
+// Created: 10 Feb 2017
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_FeatureBuilder.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_IntersectionPoint.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Point.h>
+
+#include <GeomAPI_Dir2d.h>
+#include <GeomAPI_Pnt2d.h>
+#include <GeomAPI_XY.h>
+
+static EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes);
+static EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
+ PlaneGCSSolver_Storage* theStorage,
+ std::list<GCSConstraintPtr>& theArcConstraints);
+
+
+PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(
+ PlaneGCSSolver_Storage* theStorage)
+ : PlaneGCSSolver_AttributeBuilder(theStorage)
+{
+}
+
+PlaneGCSSolver_FeatureBuilder::PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage)
+ : PlaneGCSSolver_AttributeBuilder(theStorage)
+{
+}
+
+EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createAttribute(
+ AttributePtr theAttribute)
+{
+ EntityWrapperPtr anAttr = PlaneGCSSolver_AttributeBuilder::createAttribute(theAttribute);
+ if (anAttr)
+ myAttributes[theAttribute] = anAttr;
+ return anAttr;
+}
+
+EntityWrapperPtr PlaneGCSSolver_FeatureBuilder::createFeature(FeaturePtr theFeature)
+{
+ EntityWrapperPtr aResult;
+ if (myStorage)
+ aResult = myStorage->entity(theFeature);
+ if (aResult)
+ return aResult;
+
+ // Process SketchPlugin features only
+ std::shared_ptr<SketchPlugin_Feature> aFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
+ if (!aFeature)
+ return aResult;
+
+ // Verify the feature by its kind
+ const std::string& aFeatureKind = aFeature->getKind();
+ // Line
+ if (aFeatureKind == SketchPlugin_Line::ID())
+ aResult = createLine(myAttributes);
+ // Circle
+ else if (aFeatureKind == SketchPlugin_Circle::ID())
+ aResult = createCircle(myAttributes);
+ // Arc
+ else if (aFeatureKind == SketchPlugin_Arc::ID())
+ aResult = createArc(myAttributes, myStorage, myFeatureConstraints);
+ // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
+ else if (aFeatureKind == SketchPlugin_Point::ID() ||
+ aFeatureKind == SketchPlugin_IntersectionPoint::ID()) {
+ AttributeEntityMap::const_iterator anIt = myAttributes.begin();
+ for (; anIt != myAttributes.end(); ++anIt)
+ if (anIt->first->id() == SketchPlugin_Point::COORD_ID()) {
+ aResult = anIt->second;
+ break;
+ }
+ }
+
+ if (aResult && !myStorage)
+ aResult->setExternal(true);
+
+ myAttributes.clear();
+ return aResult;
+}
+
+
+
+
+
+// ============== Auxiliary functions =====================================
+EntityWrapperPtr createLine(const AttributeEntityMap& theAttributes)
+{
+ std::shared_ptr<GCS::Line> aNewLine(new GCS::Line);
+
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (!aPoint)
+ continue;
+
+ if (anIt->first->id() == SketchPlugin_Line::START_ID())
+ aNewLine->p1 = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Line::END_ID())
+ aNewLine->p2 = *(aPoint->point());
+ }
+
+ return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewLine));
+}
+
+EntityWrapperPtr createCircle(const AttributeEntityMap& theAttributes)
+{
+ std::shared_ptr<GCS::Circle> aNewCircle(new GCS::Circle);
+
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ if (anIt->first->id() == SketchPlugin_Circle::CENTER_ID()) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ aNewCircle->center = *(aPoint->point());
+ }
+ else if(anIt->first->id() == SketchPlugin_Circle::RADIUS_ID()) {
+ ScalarWrapperPtr aScalar =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ aNewCircle->rad = aScalar->scalar();
+ }
+ }
+
+ return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewCircle));
+}
+
+static double* createParameter(PlaneGCSSolver_Storage* theStorage)
+{
+ return theStorage ? theStorage->createParameter() : (new double(0));
+}
+
+EntityWrapperPtr createArc(const AttributeEntityMap& theAttributes,
+ PlaneGCSSolver_Storage* theStorage,
+ std::list<GCSConstraintPtr>& theArcConstraints)
+{
+ std::shared_ptr<GCS::Arc> aNewArc(new GCS::Arc);
+
+ // Base attributes of arc (center, start and end points)
+ AttributeEntityMap::const_iterator anIt = theAttributes.begin();
+ for (; anIt != theAttributes.end(); ++anIt) {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ if (!aPoint)
+ continue;
+
+ if (anIt->first->id() == SketchPlugin_Arc::CENTER_ID())
+ aNewArc->center = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Arc::START_ID())
+ aNewArc->start = *(aPoint->point());
+ else if (anIt->first->id() == SketchPlugin_Arc::END_ID())
+ aNewArc->end = *(aPoint->point());
+ }
+
+ // Additional atrtributes of arc necessary for PlaneGCS solver
+ // (start and end angles, radius)
+ aNewArc->startAngle = createParameter(theStorage);
+ aNewArc->endAngle = createParameter(theStorage);
+ aNewArc->rad = createParameter(theStorage);
+
+ static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter(
+ new GeomAPI_Pnt2d(*aNewArc->center.x, *aNewArc->center.y));
+ std::shared_ptr<GeomAPI_Pnt2d> aStart(
+ new GeomAPI_Pnt2d(*aNewArc->start.x, *aNewArc->start.y));
+
+ *aNewArc->rad = aStart->distance(aCenter);
+
+ std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
+ *aNewArc->startAngle = OX->angle(aDir);
+
+ aDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d((*aNewArc->end.x) - aCenter->x(), (*aNewArc->end.y) - aCenter->y()));
+ *aNewArc->endAngle = OX->angle(aDir);
+
+ if (theStorage) {
+ // Additional constaints to fix arc's extra DoF (if the arc is not external):
+ // 1. distances from center till start and end points are equal to radius
+ theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ aNewArc->center, aNewArc->start, aNewArc->rad)));
+ theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PDistance(
+ aNewArc->center, aNewArc->end, aNewArc->rad)));
+ // 2. angles of start and end points should be equal to the arc angles
+ theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
+ aNewArc->center, aNewArc->start, aNewArc->startAngle)));
+ theArcConstraints.push_back(GCSConstraintPtr(new GCS::ConstraintP2PAngle(
+ aNewArc->center, aNewArc->end, aNewArc->endAngle)));
+ }
+
+ return EntityWrapperPtr(new PlaneGCSSolver_EntityWrapper(aNewArc));
+}
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_FeatureBuilder.h
+// Created: 10 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_FeatureBuilder_H_
+#define PlaneGCSSolver_FeatureBuilder_H_
+
+#include <PlaneGCSSolver_AttributeBuilder.h>
+
+typedef std::map<AttributePtr, EntityWrapperPtr> AttributeEntityMap;
+
+/** \class PlaneGCSSolver_FeatureBuilder
+ * \ingroup Plugins
+ * \brief Converts SketchPlugin_Feature to the entity applicable for PlaneGCS solver
+ */
+class PlaneGCSSolver_FeatureBuilder : public PlaneGCSSolver_AttributeBuilder
+{
+public:
+ PlaneGCSSolver_FeatureBuilder(PlaneGCSSolver_Storage* theStorage = 0);
+ PlaneGCSSolver_FeatureBuilder(const StoragePtr& theStorage);
+
+ /// \brief Converts an attribute to the solver's entity and stores it for further processing.
+ /// Double attributes and 2D points are supported only.
+ /// \param theAttribute [in] attribute to create
+ /// \return Created wrapper of the attribute applicable for specific solver
+ virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute) override;
+
+ /// \brief Converts SketchPlugin's feature to the solver's entity.
+ /// Result if based on the list of already converted attributes.
+ /// \param theFeature [in] feature to create
+ virtual EntityWrapperPtr createFeature(FeaturePtr theFeature) override;
+
+ /// \brief Return list of constraints necessary to fix feature's extra DoF
+ virtual const std::list<GCSConstraintPtr>& constraints() const override
+ { return myFeatureConstraints; }
+
+private:
+ /// list of converted attributes (will be cleared when the feature is created)
+ AttributeEntityMap myAttributes;
+
+ /// constraints for the feature
+ /// (primarily used for constrain arcs, which have 9 parameters but 5 DoF)
+ std::list<GCSConstraintPtr> myFeatureConstraints;
+};
+
+#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: PlaneGCSSolver_ParameterWrapper.cpp
-// Created: 14 Dec 2015
-// Author: Artem ZHIDKOV
-
-#include <PlaneGCSSolver_ParameterWrapper.h>
-
-#include <math.h>
-
-PlaneGCSSolver_ParameterWrapper::PlaneGCSSolver_ParameterWrapper(double *const theParam)
- : myValue(theParam),
- myProcessing(false)
-{
-}
-
-PlaneGCSSolver_ParameterWrapper::~PlaneGCSSolver_ParameterWrapper()
-{
- if (!myProcessing)
- delete myValue;
-}
-
-void PlaneGCSSolver_ParameterWrapper::setValue(double theValue)
-{
- *(myValue) = theValue;
-}
-
-double PlaneGCSSolver_ParameterWrapper::value() const
-{
- return *(myValue);
-}
-
-bool PlaneGCSSolver_ParameterWrapper::isEqual(const ParameterWrapperPtr& theOther)
-{
- return fabs(value() - theOther->value()) < tolerance;
-}
-
-bool PlaneGCSSolver_ParameterWrapper::update(const ParameterWrapperPtr& theOther)
-{
- if (fabs(value() - theOther->value()) < tolerance)
- return false;
- setValue(theOther->value());
- myIsParametric = theOther->isParametric();
- return true;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: PlaneGCSSolver_ParameterWrapper.h
-// Created: 14 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef PlaneGCSSolver_ParameterWrapper_H_
-#define PlaneGCSSolver_ParameterWrapper_H_
-
-#include <PlaneGCSSolver_Defs.h>
-#include <SketchSolver_IParameterWrapper.h>
-
-/**
- * Wrapper providing operations with parameters in PlaneGCS.
- */
-class PlaneGCSSolver_ParameterWrapper : public SketchSolver_IParameterWrapper
-{
-public:
- PlaneGCSSolver_ParameterWrapper(double *const theParam);
- virtual ~PlaneGCSSolver_ParameterWrapper();
-
- /// \brief Return ID of current parameter
- virtual ParameterID id() const
- { return myID; }
-
- double* parameter() const
- { return myValue; }
-
- /// \brief Change group for the parameter
- virtual void setGroup(const GroupID& theGroup)
- { myGroup = theGroup; }
-
- /// \brief Return identifier of the group the parameter belongs to
- virtual GroupID group() const
- { return myGroup; }
-
- /// \brief Change value of parameter
- virtual void setValue(double theValue);
- /// \brief Return value of parameter
- virtual double value() const;
-
- /// \brief Compare current parameter with other
- virtual bool isEqual(const ParameterWrapperPtr& theOther);
-
- /// \brief Update value of parameter by the given one
- /// \return \c true if the value of parameter is changed
- virtual bool update(const ParameterWrapperPtr& theOther);
-
- /// \brief Shows the parameter is added to full list of parameters
- bool isProcessed() const
- { return myProcessing; }
- /// \brief Set the flag that parameter is under processing
- void setProcessed(bool isProc)
- { myProcessing = isProc; }
-
-protected:
- ParameterID myID;
- GroupID myGroup;
- double* myValue;
- bool myProcessing; ///< identify that the parameter is already in the list of parameters
-};
-
-#endif
#include <PlaneGCSSolver_PointWrapper.h>
-PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(
- const AttributePtr theAttribute, const GCSPointPtr thePoint)
- : myPoint(thePoint),
- myID(EID_UNKNOWN)
+PlaneGCSSolver_PointWrapper::PlaneGCSSolver_PointWrapper(const GCSPointPtr thePoint)
+ : myPoint(thePoint)
{
- myBaseAttribute = theAttribute;
-}
-
-void PlaneGCSSolver_PointWrapper::setGroup(const GroupID& theGroup)
-{
- myGroup = theGroup;
- std::list<EntityWrapperPtr>::iterator aSubsIt = mySubEntities.begin();
- for (; aSubsIt != mySubEntities.end(); ++aSubsIt)
- (*aSubsIt)->setGroup(theGroup);
- std::list<ParameterWrapperPtr>::iterator aPIt = myParameters.begin();
- for (; aPIt != myParameters.end(); ++aPIt)
- (*aPIt)->setGroup(theGroup);
-}
-
-bool PlaneGCSSolver_PointWrapper::isUsed(AttributePtr theAttribute) const
-{
- return isBase(theAttribute);
-}
-
-bool PlaneGCSSolver_PointWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
- if (type() != theOther->type())
- return false;
-
- // Verify equality of parameters
- const std::list<ParameterWrapperPtr>& anOtherParams = theOther->parameters();
- if (myParameters.size() != anOtherParams.size())
- return false;
- std::list<ParameterWrapperPtr>::const_iterator aMyIt = myParameters.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherIt = anOtherParams.begin();
- for (; aMyIt != myParameters.end(); ++aMyIt, ++anOtherIt)
- if (!(*aMyIt)->isEqual(*anOtherIt))
- return false;
- return true;
-}
-
-bool PlaneGCSSolver_PointWrapper::update(const EntityWrapperPtr& theOther)
-{
- bool isUpdated = false;
- std::list<ParameterWrapperPtr> aMyParams = parameters();
- std::list<ParameterWrapperPtr> anOtherParams = theOther->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aMyParIt = aMyParams.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherParIt = anOtherParams.begin();
- for (; aMyParIt != aMyParams.end() && anOtherParIt != anOtherParams.end();
- ++aMyParIt, ++anOtherParIt)
- isUpdated = (*aMyParIt)->update(*anOtherParIt);
- return isUpdated;
}
class PlaneGCSSolver_PointWrapper : public SketchSolver_IEntityWrapper
{
public:
- PlaneGCSSolver_PointWrapper(const AttributePtr theAttribute, const GCSPointPtr thePoint);
+ PlaneGCSSolver_PointWrapper(const GCSPointPtr thePoint);
/// \brief Return PlaneGCS point
const GCSPointPtr& point() const
GCSPointPtr& changeEntity()
{ return myPoint; }
- /// \brief Return ID of current entity
- virtual EntityID id() const
- { return myID; }
- /// \brief Change ID of the entity
- void setId(EntityID theID)
- { myID = theID; }
-
- /// \brief Change group for the entity
- virtual void setGroup(const GroupID& theGroup);
- /// \brief Return identifier of the group the entity belongs to
- virtual GroupID group() const
- { return myGroup; }
-
/// \brief Return type of current entity
virtual SketchSolver_EntityType type() const
{ return ENTITY_POINT; }
- /// \brief Verify the feature is used in the entity
- virtual bool isUsed(FeaturePtr theFeature) const
- { return false; }
- /// \brief Verify the attribute is used in the entity
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Compare current entity with other
- virtual bool isEqual(const EntityWrapperPtr& theOther);
-
- /// \brief Update values of parameters of this entity by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const EntityWrapperPtr& theOther);
-
private:
- EntityID myID;
- GroupID myGroup;
GCSPointPtr myPoint;
};
// Author: Artem ZHIDKOV
#include <PlaneGCSSolver_ScalarWrapper.h>
-#include <PlaneGCSSolver_ParameterWrapper.h>
+#include <cmath>
-
-PlaneGCSSolver_ScalarWrapper::PlaneGCSSolver_ScalarWrapper(
- const AttributePtr theAttribute,
- const ParameterWrapperPtr theParam)
-{
- myBaseAttribute = theAttribute;
- myParameters.assign(1, theParam);
-}
-
-void PlaneGCSSolver_ScalarWrapper::setGroup(const GroupID& theGroup)
+PlaneGCSSolver_ScalarWrapper::PlaneGCSSolver_ScalarWrapper(double *const theParam)
+ : myValue(theParam)
{
- myGroup = theGroup;
- myParameters.front()->setGroup(theGroup);
}
-double* PlaneGCSSolver_ScalarWrapper::scalar() const
+void PlaneGCSSolver_ScalarWrapper::setValue(double theValue)
{
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(myParameters.front());
- return aParam->parameter();
-}
-
-bool PlaneGCSSolver_ScalarWrapper::isUsed(AttributePtr theAttribute) const
-{
- return isBase(theAttribute);
-}
-
-bool PlaneGCSSolver_ScalarWrapper::isEqual(const EntityWrapperPtr& theOther)
-{
- if (type() != theOther->type())
- return false;
-
- // Verify equality of parameters
- const std::list<ParameterWrapperPtr>& anOtherParams = theOther->parameters();
- if (myParameters.size() != anOtherParams.size())
- return false;
- std::list<ParameterWrapperPtr>::const_iterator aMyIt = myParameters.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherIt = anOtherParams.begin();
- for (; aMyIt != myParameters.end(); ++aMyIt, ++anOtherIt)
- if (!(*aMyIt)->isEqual(*anOtherIt))
- return false;
- return true;
+ *myValue = theValue;
}
-bool PlaneGCSSolver_ScalarWrapper::update(const EntityWrapperPtr& theOther)
+double PlaneGCSSolver_ScalarWrapper::value() const
{
- bool isUpdated = false;
- std::list<ParameterWrapperPtr> aMyParams = parameters();
- std::list<ParameterWrapperPtr> anOtherParams = theOther->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aMyParIt = aMyParams.begin();
- std::list<ParameterWrapperPtr>::const_iterator anOtherParIt = anOtherParams.begin();
- for (; aMyParIt != aMyParams.end() && anOtherParIt != anOtherParams.end();
- ++aMyParIt, ++anOtherParIt)
- isUpdated = (*aMyParIt)->update(*anOtherParIt);
- return isUpdated;
+ return *myValue;
}
class PlaneGCSSolver_ScalarWrapper : public SketchSolver_IEntityWrapper
{
public:
- PlaneGCSSolver_ScalarWrapper(const AttributePtr theAttribute, const ParameterWrapperPtr theParam);
+ PlaneGCSSolver_ScalarWrapper(double *const theParam);
/// \brief Return PlaneGCS parameter
- double* scalar() const;
+ double* scalar() const
+ { return myValue; }
- /// \brief Return ID of current entity
- virtual EntityID id() const
- { return myID; }
- /// \brief Change ID of the entity
- void setId(EntityID theID)
- { myID = theID; }
-
- /// \brief Change group for the entity
- virtual void setGroup(const GroupID& theGroup);
- /// \brief Return identifier of the group the entity belongs to
- virtual GroupID group() const
- { return myGroup; }
+ /// \brief Change value of parameter
+ virtual void setValue(double theValue);
+ /// \brief Return value of parameter
+ virtual double value() const;
/// \brief Return type of current entity
virtual SketchSolver_EntityType type() const
{ return ENTITY_SCALAR; }
- /// \brief Verify the feature is used in the entity
- virtual bool isUsed(FeaturePtr theFeature) const
- { return false; }
- /// \brief Verify the attribute is used in the entity
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Compare current entity with other
- virtual bool isEqual(const EntityWrapperPtr& theOther);
-
- /// \brief Update values of parameters of this entity by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const EntityWrapperPtr& theOther);
-
-private:
- EntityID myID;
- GroupID myGroup;
+protected:
+ double* myValue; ///< pointer to value provided by the storage
};
+typedef std::shared_ptr<PlaneGCSSolver_ScalarWrapper> ScalarWrapperPtr;
+
#endif
#include "PlaneGCSSolver_Solver.h"
#include <Events_LongOp.h>
-#include <cmath>
-
-// remove indices of all point-point coincidences from the vector
-static void removePtPtCoincidences(const ConstraintMap& theConstraints, GCS::VEC_I& theVecToClear)
-{
- ConstraintMap::const_iterator aCIt = theConstraints.begin();
- for (; aCIt != theConstraints.end(); ++aCIt) {
- if (aCIt->second != CONSTRAINT_PT_PT_COINCIDENT)
- continue;
- GCS::VEC_I::iterator aRIt = theVecToClear.begin();
- for (; aRIt != theVecToClear.end(); ++aRIt)
- if (aCIt->first->getTag() == *aRIt) {
- theVecToClear.erase(aRIt);
- break;
- }
- }
-}
-
PlaneGCSSolver_Solver::PlaneGCSSolver_Solver()
: myEquationSystem(new GCS::System),
- myConfCollected(false)
+ myConfCollected(false)
{
}
void PlaneGCSSolver_Solver::clear()
{
myEquationSystem->clear();
- myConstraints.clear();
myParameters.clear();
+ myEqualConstraints.clear();
+ myEqualParameters.clear();
}
-void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint,
- const SketchSolver_ConstraintType theType)
+void PlaneGCSSolver_Solver::addConstraint(GCSConstraintPtr theConstraint)
{
- GCS::Constraint* aConstraint = theConstraint.get();
- if (myConstraints.find(aConstraint) != myConstraints.end())
- return; // constraint already exists, no need to add it again
-
- myEquationSystem->addConstraint(aConstraint);
- myConstraints[aConstraint] = theType;
+ myEquationSystem->addConstraint(theConstraint.get());
}
-void PlaneGCSSolver_Solver::removeConstraint(GCSConstraintPtr theConstraint)
+void PlaneGCSSolver_Solver::removeConstraint(ConstraintID theID)
{
- GCS::Constraint* aConstraint = theConstraint.get();
- removeConstraint(aConstraint);
-}
-
-void PlaneGCSSolver_Solver::removeConstraint(GCS::Constraint* theConstraint)
-{
- if (myConstraints.find(theConstraint) == myConstraints.end())
- return; // no constraint, no need to remove it
-
- myEquationSystem->removeConstraint(theConstraint);
- myConstraints.erase(theConstraint);
+ myEquationSystem->clearByTag(theID);
}
SketchSolver_SolveStatus PlaneGCSSolver_Solver::solve()
myConfCollected = false;
}
- if (myConstraints.empty())
- return STATUS_EMPTYSET;
if (myParameters.empty())
return STATUS_INCONSISTENT;
Events_LongOp::start(this);
- GCS::SolveStatus aResult = GCS::Success;
- // if there is a constraint with all attributes constant, set fail status
- GCS::SET_pD aParameters;
- aParameters.insert(myParameters.begin(), myParameters.end());
- ConstraintMap::const_iterator aConstrIt = myConstraints.begin();
- for (; aConstrIt != myConstraints.end(); ++aConstrIt) {
- GCS::VEC_pD aParams = aConstrIt->first->params();
- GCS::VEC_pD::const_iterator aPIt = aParams.begin();
- for (; aPIt != aParams.end(); ++aPIt)
- if (aParameters.find(*aPIt) != aParameters.end())
- break;
- if (aPIt == aParams.end() && aConstrIt->first->getTag() > 0) {
- myConflictingIDs.insert(aConstrIt->first->getTag());
- myConfCollected = true;
- aResult = GCS::Failed;
- }
- }
// solve equations
- if (aResult == GCS::Success)
- aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
-
- GCS::VEC_I aRedundantID;
-
- // Workaround: the system with tangent constraint
- // may fail if the tangent entities are connected smoothly.
- // Investigate this situation and move constraints to redundant list
- if (aResult == GCS::Failed && !myTangent.empty()) {
- GCS::VEC_I aConflictingID;
- myEquationSystem->getConflicting(aConflictingID);
- GCS::VEC_I::iterator aCIt = aConflictingID.begin();
- for (; aCIt != aConflictingID.end(); ++ aCIt) {
- if (myTangent.find(*aCIt) == myTangent.end())
- continue;
- if (isTangentTruth(*aCIt))
- aRedundantID.push_back(*aCIt);
- }
-
- if (!aRedundantID.empty())
- aResult = GCS::Success; // check redundant constraints
- }
-
- // Additionally check redundant constraints
- if (aResult == GCS::Success || aResult == GCS::Converged) {
- bool isSolveWithoutTangent = !aRedundantID.empty();
- GCS::VEC_I aRedundantLocal;
- myEquationSystem->getRedundant(aRedundantLocal);
- aRedundantID.insert(aRedundantID.end(), aRedundantLocal.begin(), aRedundantLocal.end());
- // Workaround: remove all point-point coincidences from list of redundant
- if (!aRedundantID.empty())
- removePtPtCoincidences(myConstraints, aRedundantID);
- // The system with tangent constraints may show redundant constraints
- // if the entities are coupled smoothly.
- // Sometimes tangent constraints are fall to both conflicting and redundant constraints.
- // Need to check if there are redundant constraints without these tangencies.
- if (!aRedundantID.empty() && !isSolveWithoutTangent) {
- GCS::VEC_I::iterator aCIt = aRedundantID.begin();
- for (; aCIt != aRedundantID.end(); ++ aCIt)
- if (myTangent.find(*aCIt) != myTangent.end()) {
- isSolveWithoutTangent = true;
- break;
- }
- }
- if (isSolveWithoutTangent)
- aResult = myTangent.empty() ? GCS::Failed : solveWithoutTangent();
- else
- aResult = GCS::Success;
- }
+ GCS::SolveStatus aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
Events_LongOp::end(this);
SketchSolver_SolveStatus aStatus;
return aStatus;
}
-GCS::SolveStatus PlaneGCSSolver_Solver::solveWithoutTangent()
-{
- std::shared_ptr<GCS::System> aSystemWithoutTangent(new GCS::System);
-
- // Remove tangency which leads to redundant or conflicting constraints
- GCS::VEC_I aConflicting, aRedundant;
- myEquationSystem->getRedundant(aRedundant);
- size_t aNbRemove = myTangent.size(); // number of tangent constraints which can be removed
- myEquationSystem->getConflicting(aConflicting);
- aRedundant.insert(aRedundant.end(), aConflicting.begin(), aConflicting.end());
-
- GCS::SET_I aTangentToRemove;
- GCS::VEC_I::iterator aCIt = aRedundant.begin();
- for (; aCIt != aRedundant.end() && aNbRemove > 0; ++aCIt)
- if (myTangent.find(*aCIt) != myTangent.end()) {
- aTangentToRemove.insert(*aCIt);
- --aNbRemove;
- }
-
- std::set<GCS::Constraint*> aRemovedTangent;
- ConstraintMap::const_iterator aConstrIt = myConstraints.begin();
- while (aConstrIt != myConstraints.end()) {
- GCS::Constraint* aConstraint = aConstrIt->first;
- int anID = aConstraint->getTag();
- ++aConstrIt;
- if (aTangentToRemove.find(anID) == aTangentToRemove.end())
- aSystemWithoutTangent->addConstraint(aConstraint);
- else
- aRemovedTangent.insert(aConstraint);
- }
-
- myTangent.clear();
- GCS::SolveStatus aResult = (GCS::SolveStatus)aSystemWithoutTangent->solve(myParameters);
- if (aResult == GCS::Success) {
- GCS::VEC_I aRedundant;
- aSystemWithoutTangent->getRedundant(aRedundant);
- if (!aRedundant.empty()) {
- removePtPtCoincidences(myConstraints, aRedundant);
- if (!aRedundant.empty())
- aResult = GCS::Failed;
- }
- }
-
- // additional check that removed constraints are still correct
- if (aResult == GCS::Success) {
- aSystemWithoutTangent->applySolution();
- std::set<GCS::Constraint*>::const_iterator aRemIt = aRemovedTangent.begin();
- for (; aRemIt != aRemovedTangent.end(); ++aRemIt)
- if (!isTangentTruth(*aRemIt))
- break;
- if (aRemIt != aRemovedTangent.end()) {
- aResult = (GCS::SolveStatus)myEquationSystem->solve(myParameters);
- if (aResult != GCS::Failed) {
- aSystemWithoutTangent = myEquationSystem;
- aResult = GCS::Success;
- }
- }
- }
-
- if (aResult == GCS::Success)
- myEquationSystem = aSystemWithoutTangent;
- else {
- // Add IDs of removed tangent to the list of conflicting constraints
- std::set<GCS::Constraint*>::const_iterator aRemIt = aRemovedTangent.begin();
- for (; aRemIt != aRemovedTangent.end(); ++aRemIt)
- myConflictingIDs.insert((*aRemIt)->getTag());
- }
-
- return aResult;
-}
-
-bool PlaneGCSSolver_Solver::isTangentTruth(GCS::Constraint* theTangent) const
-{
- if (theTangent->getTypeId() == GCS::TangentCircumf) {
- static const double aTol = 1e-4;
- GCS::VEC_pD aParams = theTangent->params();
- double dx = *(aParams[2]) - *(aParams[0]);
- double dy = *(aParams[3]) - *(aParams[1]);
- double aDist2 = dx * dx + dy * dy;
- double aRadSum = *(aParams[4]) + *(aParams[5]);
- double aRadDiff = *(aParams[4]) - *(aParams[5]);
- double aTol2 = aTol * aRadSum;
- aTol2 *= aTol2;
- return fabs(aDist2 - aRadSum * aRadSum) <= aTol2 ||
- fabs(aDist2 - aRadDiff * aRadDiff) <= aTol2;
- }
- if (theTangent->getTypeId() == GCS::P2LDistance) {
- static const double aTol2 = 1e-10;
- GCS::VEC_pD aParams = theTangent->params();
- double aDist2 = *(aParams[6]) * *(aParams[6]);
- // orthogonal line direction
- double aDirX = *(aParams[5]) - *(aParams[3]);
- double aDirY = *(aParams[2]) - *(aParams[4]);
- double aLen2 = aDirX * aDirX + aDirY * aDirY;
- // vector from line's start to point
- double aVecX = *(aParams[0]) - *(aParams[2]);
- double aVecY = *(aParams[1]) - *(aParams[3]);
-
- double aDot = aVecX * aDirX + aVecY * aDirY;
- return fabs(aDot * aDot - aDist2 * aLen2) <= aTol2 * aLen2;
- }
- return false;
-}
-
-bool PlaneGCSSolver_Solver::isTangentTruth(int theTagID) const
-{
- ConstraintMap::const_iterator anIt = myConstraints.begin();
- for (; anIt != myConstraints.end(); ++anIt)
- if (anIt->first->getTag() == theTagID)
- return isTangentTruth(anIt->first);
- return false;
-}
-
void PlaneGCSSolver_Solver::undo()
{
myEquationSystem->undoSolution();
#include <GCS.h>
-typedef std::map<GCS::Constraint*, SketchSolver_ConstraintType> ConstraintMap;
-
-/**
- * The main class that performs the high-level operations for connection to the PlaneGCS.
- */
+/// \brief The main class that performs the high-level operations for connection to the PlaneGCS.
class PlaneGCSSolver_Solver : public SketchSolver_ISolver
{
public:
void clear();
/// \brief Add constraint to the system of equations
- void addConstraint(GCSConstraintPtr theConstraint,
- const SketchSolver_ConstraintType theType);
+ void addConstraint(GCSConstraintPtr theConstraint);
/// \brief Remove constraint from the system of equations
- void removeConstraint(GCSConstraintPtr theConstraint);
+ void removeConstraint(ConstraintID theID);
/// \brief Initialize list of unknowns
void setParameters(const GCS::VEC_pD& theParams)
{ myParameters = theParams; }
- /// \brief Set list of IDs of tangent constraints
- ///
- /// Workaround to avoid incorrect report about redundant constraints
- /// if an arc is already smoothly connected to a line.
- void setTangent(const GCS::SET_I& theTangentIDs)
- { myTangent = theTangentIDs; }
-
- /** \brief Solve the set of equations
- * \return identifier whether solution succeeded
- */
- virtual SketchSolver_SolveStatus solve();
+ /// \brief Solve the set of equations
+ /// \return identifier whether solution succeeded
+ virtual SketchSolver_SolveStatus solve() override;
/// \brief Prepare for solving. Store initial values of parameters for undo
- virtual void prepare()
+ virtual void prepare() override
{ /* do nothing */ }
/// \brief Revert solution to initial values
- virtual void undo();
+ virtual void undo() override;
/// \brief Check the constraint is conflicted with others
- virtual bool isConflicting(const ConstraintID& theConstraint) const;
+ virtual bool isConflicting(const ConstraintID& theConstraint) const override;
/// \brief Degrees of freedom
- virtual int dof() const;
+ virtual int dof() const override;
private:
void collectConflicting();
- /// \brief Remove constraint from the system of equations
- void removeConstraint(GCS::Constraint* theConstraint);
-
- /// \brief Remove redundant tangent constraints and try to solve the system again
- GCS::SolveStatus solveWithoutTangent();
-
- /// \brief Check the entities under the tangent constraint are smoothly connected
- bool isTangentTruth(int theTagID) const;
- /// \brief Check the entities under the tangent constraint are smoothly connected
- bool isTangentTruth(GCS::Constraint* theTangent) const;
-
private:
GCS::VEC_pD myParameters; ///< list of unknowns
-
- /// list of constraints already processed by the system
- ConstraintMap myConstraints;
std::shared_ptr<GCS::System> myEquationSystem; ///< set of equations for solving in FreeGCS
GCS::SET_I myConflictingIDs; ///< list of IDs of conflicting constraints
/// specifies the conflicting constraints are already collected
bool myConfCollected;
- /// list of tangent IDs to check incorrect redundant constraints
- GCS::SET_I myTangent;
+ /// lists of parameters used in the Equal constraints (to avoid multiple equalities)
+ std::list<GCS::SET_pD> myEqualParameters;
+ /// lists of the Equal constraints
+ std::map<ConstraintID, std::set<GCSConstraintPtr> > myEqualConstraints;
};
#endif
#include <PlaneGCSSolver_ConstraintWrapper.h>
#include <PlaneGCSSolver_EntityWrapper.h>
#include <PlaneGCSSolver_PointWrapper.h>
-#include <PlaneGCSSolver_ScalarWrapper.h>
-#include <PlaneGCSSolver_ParameterWrapper.h>
-#include <GeomAPI_Edge.h>
+#include <PlaneGCSSolver_AttributeBuilder.h>
+#include <PlaneGCSSolver_FeatureBuilder.h>
+#include <PlaneGCSSolver_EntityDestroyer.h>
+
#include <GeomAPI_Dir2d.h>
#include <GeomAPI_Pnt2d.h>
#include <GeomAPI_XY.h>
#include <GeomDataAPI_Point2D.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_ConstraintTangent.h>
+#include <SketchPlugin_Projection.h>
#include <cmath>
-PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const GroupID& theGroup)
- : SketchSolver_Storage(theGroup),
- myEntityLastID(EID_SKETCH),
+static void constraintsToSolver(const ConstraintWrapperPtr& theConstraint,
+ const SolverPtr& theSolver)
+{
+ std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
+ if (!aSolver)
+ return;
+
+ const std::list<GCSConstraintPtr>& aConstraints =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint)->constraints();
+ std::list<GCSConstraintPtr>::const_iterator anIt = aConstraints.begin();
+ for (; anIt != aConstraints.end(); ++anIt)
+ aSolver->addConstraint(*anIt);
+}
+
+
+PlaneGCSSolver_Storage::PlaneGCSSolver_Storage(const SolverPtr& theSolver)
+ : SketchSolver_Storage(theSolver),
myConstraintLastID(CID_UNKNOWN)
{
}
void PlaneGCSSolver_Storage::addConstraint(
- ConstraintPtr theConstraint,
- std::list<ConstraintWrapperPtr> theSolverConstraints)
+ ConstraintPtr theConstraint,
+ ConstraintWrapperPtr theSolverConstraint)
{
- SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraints);
-
- // update point-point coincidence
- if (!theSolverConstraints.empty() &&
- theSolverConstraints.front()->type() == CONSTRAINT_PT_PT_COINCIDENT) {
- std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
- for (; aCIt != theSolverConstraints.end(); ++aCIt)
- update(*aCIt);
- }
+ SketchSolver_Storage::addConstraint(theConstraint, theSolverConstraint);
+
+ theSolverConstraint->setId(++myConstraintLastID);
+ constraintsToSolver(theSolverConstraint, mySketchSolver);
+}
+
+void PlaneGCSSolver_Storage::addTemporaryConstraint(
+ const ConstraintWrapperPtr& theSolverConstraint)
+{
+ if (myConstraintMap.empty())
+ return; // no need to process temporary constraints if there is no active constraint
+
+ theSolverConstraint->setId(CID_MOVEMENT);
+ constraintsToSolver(theSolverConstraint, mySketchSolver);
}
-bool PlaneGCSSolver_Storage::update(ConstraintWrapperPtr theConstraint)
+EntityWrapperPtr PlaneGCSSolver_Storage::createFeature(
+ const FeaturePtr& theFeature,
+ PlaneGCSSolver_EntityBuilder* theBuilder)
{
- bool isUpdated = false;
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-
- // point-Line distance should be positive
- if (aConstraint->type() == CONSTRAINT_PT_LINE_DISTANCE && aConstraint->value() < 0.0)
- aConstraint->setValue(-aConstraint->value());
-
- // make value of constraint unchangeable
- ParameterWrapperPtr aValue = aConstraint->valueParameter();
- if (aValue)
- isUpdated = update(aValue) || isUpdated;
-
- // update constrained entities
- std::list<EntityWrapperPtr> anEntities = theConstraint->entities();
- std::list<EntityWrapperPtr>::iterator anIt = anEntities.begin();
- for (; anIt != anEntities.end(); ++anIt)
- isUpdated = update(*anIt) || isUpdated;
-
- if (aConstraint->id() == CID_UNKNOWN) {
- const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
- // check middle-point constraint conflicts with point-on-line
- if (aConstraint->type() == CONSTRAINT_MIDDLE_POINT) {
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- anIt = myConstraintMap.begin();
- for (; anIt != myConstraintMap.end(); ++anIt) {
- EntityWrapperPtr aPoint, aLine;
- if (anIt->second.empty())
- continue;
- ConstraintWrapperPtr aCurrentConstr = anIt->second.front();
- if (aCurrentConstr->type() != CONSTRAINT_PT_ON_LINE)
- continue;
- const std::list<EntityWrapperPtr>& aCurSubs = aCurrentConstr->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt1, aSIt2;
- for (aSIt1 = aSubs.begin(); aSIt1 != aSubs.end(); ++aSIt1) {
- if ((*aSIt1)->type() == ENTITY_POINT)
- aPoint = *aSIt1;
- else if((*aSIt1)->type() == ENTITY_LINE)
- aLine = *aSIt1;
- else
- continue;
- for (aSIt2 = aCurSubs.begin(); aSIt2 != aCurSubs.end(); ++aSIt2)
- if ((*aSIt1)->id() == (*aSIt2)->id())
- break;
- if (aSIt2 == aCurSubs.end())
- break;
- }
- // point-on-line found, change it to bisector
- if (aSIt1 == aSubs.end()) {
- std::list<GCSConstraintPtr> aConstrList = aConstraint->constraints();
- aConstrList.pop_front();
- aConstraint->setConstraints(aConstrList);
- break;
- }
- }
- }
+ std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+ std::list<AttributePtr>::const_iterator anIt = anAttributes.begin();
+ for (; anIt != anAttributes.end(); ++anIt)
+ createAttribute(*anIt, theBuilder);
+
+ EntityWrapperPtr aResult = theBuilder->createFeature(theFeature);
+ if (aResult)
+ addEntity(theFeature, aResult);
+ return aResult;
+}
- // Change ID of constraints
- aConstraint->setId(++myConstraintLastID);
- }
+EntityWrapperPtr PlaneGCSSolver_Storage::createAttribute(
+ const AttributePtr& theAttribute,
+ PlaneGCSSolver_EntityBuilder* theBuilder)
+{
+ EntityWrapperPtr aResult = theBuilder->createAttribute(theAttribute);
+ if (aResult)
+ addEntity(theAttribute, aResult);
+ return aResult;
+}
+/// \brief Update value
+static bool updateValue(const double& theSource, double& theDest)
+{
+ static const double aTol = 1000. * tolerance;
+ bool isUpdated = fabs(theSource - theDest) > aTol;
+ if (isUpdated)
+ theDest = theSource;
return isUpdated;
}
/// \brief Update coordinates of the point or scalar using its base attribute
-static bool updateValues(EntityWrapperPtr& theEntity)
+static bool updateValues(AttributePtr& theAttribute, EntityWrapperPtr& theEntity)
{
- const double aTol = 1000. * tolerance;
bool isUpdated = false;
- AttributePtr anAttr = theEntity->baseAttribute();
- const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
-
- double aCoord[2];
std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr);
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
if (aPoint2D) {
- aCoord[0] = aPoint2D->x();
- aCoord[1] = aPoint2D->y();
+ const GCSPointPtr& aGCSPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity)->point();
+ isUpdated = updateValue(aPoint2D->x(), *(aGCSPoint->x)) || isUpdated;
+ isUpdated = updateValue(aPoint2D->y(), *(aGCSPoint->y)) || isUpdated;
} else {
- AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
- if (aScalar)
- aCoord[0] = aScalar->value();
- }
-
- std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
- for (int i = 0; anIt != aParams.end(); ++anIt, ++i)
- if (fabs((*anIt)->value() - aCoord[i]) > aTol) {
- (*anIt)->setValue(aCoord[i]);
- isUpdated = true;
- }
- return isUpdated;
-}
-
-bool PlaneGCSSolver_Storage::update(EntityWrapperPtr theEntity)
-{
- if (theEntity->type() == ENTITY_SKETCH)
- return true; // sketch is not necessary for PlaneGCS, so it is always says true
-
- bool isUpdated = false;
-
- if (theEntity->baseAttribute()) {
- isUpdated = updateValues(theEntity);
- if (isUpdated) {
- setNeedToResolve(true);
- if (theEntity->type() == ENTITY_POINT && theEntity->group() != myGroupID)
- updateCoincident(theEntity);
- }
- }
-
- // update parameters
- std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
- std::list<ParameterWrapperPtr>::iterator aPIt = aParams.begin();
- for (; aPIt != aParams.end(); ++aPIt)
- isUpdated = update(*aPIt) || isUpdated;
-
- // update sub-entities
- std::list<EntityWrapperPtr> aSubEntities = theEntity->subEntities();
- std::list<EntityWrapperPtr>::iterator aSIt = aSubEntities.begin();
- for (; aSIt != aSubEntities.end(); ++aSIt)
- isUpdated = update(*aSIt) || isUpdated;
-
- // additional constraints for the arc processing
- if (theEntity->type() == ENTITY_ARC)
- processArc(theEntity);
-
- // Change entity's ID, if necessary
- if (theEntity->id() == EID_UNKNOWN) {
- if (theEntity->type() == ENTITY_POINT) {
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
- if (!aPoint) {
- aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
- theEntity->subEntities().front());
- }
- aPoint->setId(++myEntityLastID);
- } else if (theEntity->type() == ENTITY_SCALAR) {
- std::shared_ptr<PlaneGCSSolver_ScalarWrapper> aScalar =
+ AttributeDoublePtr aScalar =
+ std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theAttribute);
+ if (aScalar) {
+ ScalarWrapperPtr aWrapper =
std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(theEntity);
- aScalar->setId(++myEntityLastID);
- } else {
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> aGCSEnt =
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theEntity);
- aGCSEnt->setId(++myEntityLastID);
+ // There is possible angular value, which is converted between degrees and radians.
+ // So, we use its value instead of using direct pointer to value.
+ double aValue = aWrapper->value();
+ isUpdated = updateValue(aScalar->value(), aValue);
+ if (isUpdated)
+ aWrapper->setValue(aValue);
}
}
- return isUpdated;
-}
-
-bool PlaneGCSSolver_Storage::update(ParameterWrapperPtr theParameter)
-{
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
- if (aParam->isProcessed())
- return false;
- if (theParameter->group() != myGroupID || theParameter->isParametric())
- myConst.push_back(aParam->parameter());
- else
- myParameters.push_back(aParam->parameter());
- aParam->setProcessed(true);
- return true;
-}
-
-bool PlaneGCSSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
-{
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(theConstraint);
-
- bool isFullyRemoved = true;
- // remove point-point coincidence
- if (aConstraint->type() == CONSTRAINT_PT_PT_COINCIDENT)
- isFullyRemoved = removeCoincidence(theConstraint) && isFullyRemoved;
- // remove sub-entities
- const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (; aSIt != aSubs.end(); ++ aSIt)
- isFullyRemoved = remove(*aSIt) && isFullyRemoved;
-
- if (aConstraint->valueParameter())
- isFullyRemoved = remove(aConstraint->valueParameter()) && isFullyRemoved;
- if (!isFullyRemoved && aConstraint->baseConstraint() &&
- (!aConstraint->baseConstraint()->data() || !aConstraint->baseConstraint()->data()->isValid()))
- isFullyRemoved = true;
- setNeedToResolve(true);
- myRemovedConstraints.insert(myRemovedConstraints.end(),
- aConstraint->constraints().begin(), aConstraint->constraints().end());
-
- if (isFullyRemoved && theConstraint->id() == myConstraintLastID)
- --myConstraintLastID;
-
- return isFullyRemoved;
+ return isUpdated;
}
-bool PlaneGCSSolver_Storage::remove(EntityWrapperPtr theEntity)
+static bool isCopyInMulti(std::shared_ptr<SketchPlugin_Feature> theFeature)
{
- // do not remove entity, if it is used by constraints or other entities
- if ((theEntity->baseFeature() && isUsed(theEntity->baseFeature())) ||
- (theEntity->baseAttribute() && isUsed(theEntity->baseAttribute())))
+ if (!theFeature)
return false;
- bool isFullyRemoved = SketchSolver_Storage::remove(theEntity);
- if (isFullyRemoved) {
- if (theEntity->type() == ENTITY_ARC) {
- // remove arc additional constraints
- std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::iterator
- aFound = myArcConstraintMap.find(theEntity);
- if (aFound != myArcConstraintMap.end()) {
- myRemovedConstraints.insert(myRemovedConstraints.end(),
- aFound->second.begin(), aFound->second.end());
- myArcConstraintMap.erase(aFound);
- }
+ bool aResult = theFeature->isCopy();
+ if (aResult) {
+ const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
+ for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
+ aRefIt != aRefs.end() && aResult; ++aRefIt) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+ if (anOwner->getKind() == SketchPlugin_Projection::ID())
+ aResult = false;
}
- if (theEntity->id() == myEntityLastID)
- --myEntityLastID;
}
- return isFullyRemoved;
+ return aResult;
}
-bool PlaneGCSSolver_Storage::remove(ParameterWrapperPtr theParameter)
+bool PlaneGCSSolver_Storage::update(FeaturePtr theFeature, bool theForce)
{
- std::shared_ptr<PlaneGCSSolver_ParameterWrapper> aParam =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(theParameter);
- if (aParam->isProcessed()) {
- double* aValPtr = aParam->parameter();
- GCS::VEC_pD::iterator anIt = myParameters.begin();
- for (; anIt != myParameters.end(); ++anIt)
- if (*anIt == aValPtr)
- break;
- if (anIt != myParameters.end()) {
- myParameters.erase(anIt);
- setNeedToResolve(true);
- aParam->setProcessed(false);
- }
- else {
- for (anIt = myConst.begin(); anIt != myConst.end(); ++anIt)
- if (*anIt == aValPtr)
- break;
- if (anIt != myConst.end()) {
- myConst.erase(anIt);
- setNeedToResolve(true);
- aParam->setProcessed(false);
- }
+ bool isUpdated = false;
+ EntityWrapperPtr aRelated = entity(theFeature);
+ if (aRelated) // send signal to subscribers
+ notify(theFeature);
+ else { // Feature is not exist, create it
+ std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
+ bool isCopy = isCopyInMulti(aSketchFeature);
+ // the feature is a copy in "Multi" constraint and does not used in other constraints
+ if (!theForce && isCopy && myFeatureMap.find(theFeature) == myFeatureMap.end())
+ return false;
+
+ // external feature processing
+ bool isExternal = (aSketchFeature && (aSketchFeature->isExternal() || isCopy));
+
+ PlaneGCSSolver_FeatureBuilder aBuilder(isExternal ? 0 : this);
+
+ // Reserve the feature in the map of features
+ // (do not want to add several copies of it while adding attributes)
+ aRelated = createFeature(theFeature, &aBuilder);
+ myFeatureMap[theFeature] = aRelated;
+
+ const std::list<GCSConstraintPtr>& aConstraints = aBuilder.constraints();
+ if (!aConstraints.empty()) { // the feature is arc
+ /// TODO: avoid this workaround
+ ConstraintWrapperPtr aWrapper(
+ new PlaneGCSSolver_ConstraintWrapper(aConstraints, CONSTRAINT_UNKNOWN));
+ aWrapper->setId(++myConstraintLastID);
+ constraintsToSolver(aWrapper, mySketchSolver);
+
+ myArcConstraintMap[myFeatureMap[theFeature]] = aWrapper;
}
+ isUpdated = true;
}
- return true;
-}
+ std::list<AttributePtr> anAttributes = theFeature->data()->attributes(std::string());
+ std::list<AttributePtr>::iterator anAttrIt = anAttributes.begin();
+ for (; anAttrIt != anAttributes.end(); ++anAttrIt)
+ if ((*anAttrIt)->attributeType() == GeomDataAPI_Point2D::typeId() ||
+ (*anAttrIt)->attributeType() == ModelAPI_AttributeDouble::typeId())
+ isUpdated = update(*anAttrIt) || isUpdated;
-void PlaneGCSSolver_Storage::addCoincidentPoints(
- EntityWrapperPtr theMaster, EntityWrapperPtr theSlave)
-{
- if (theMaster->type() != ENTITY_POINT || theSlave->type() != ENTITY_POINT)
- return;
-
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aMaster =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theMaster);
- if (!aMaster)
- aMaster = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theMaster)->subEntities().front());
- std::shared_ptr<PlaneGCSSolver_PointWrapper> aSlave =
- std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theSlave);
- if (!aSlave)
- aSlave = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theSlave)->subEntities().front());
-
- // Search available coincidence
- CoincidentPointsMap::iterator aMasterFound = myCoincidentPoints.find(aMaster);
- CoincidentPointsMap::iterator aSlaveFound = myCoincidentPoints.find(aSlave);
- if (aMasterFound == myCoincidentPoints.end() && aSlaveFound == myCoincidentPoints.end()) {
- // try to find master and slave points in the lists of slaves of already existent coincidences
- CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
- for (; anIt != myCoincidentPoints.end(); ++anIt) {
- if (anIt->second.find(aMaster) != anIt->second.end())
- aMasterFound = anIt;
- else if (anIt->second.find(aSlave) != anIt->second.end())
- aSlaveFound = anIt;
-
- if (aMasterFound != myCoincidentPoints.end() && aSlaveFound != myCoincidentPoints.end())
- break;
- }
- }
+ // update arc
+ if (aRelated && aRelated->type() == ENTITY_ARC) {
+ /// TODO: this code should be shared with FeatureBuilder somehow
- if (aMasterFound == myCoincidentPoints.end()) {
- // create new group
- myCoincidentPoints[aMaster] = std::set<EntityWrapperPtr>();
- aMasterFound = myCoincidentPoints.find(aMaster);
- } else if (aMasterFound == aSlaveFound)
- return; // already coincident
-
- if (aSlaveFound != myCoincidentPoints.end()) {
- // A slave has been found, we need to attach all points coincident with it to the new master
- std::set<EntityWrapperPtr> aNewSlaves = aSlaveFound->second;
- aNewSlaves.insert(aSlaveFound->first);
- myCoincidentPoints.erase(aSlaveFound);
-
- std::set<EntityWrapperPtr>::const_iterator aSlIt = aNewSlaves.begin();
- for (; aSlIt != aNewSlaves.end(); ++aSlIt)
- addCoincidentPoints(aMaster, *aSlIt);
- } else {
- //std::list<ParameterWrapperPtr> aSlaveParams = aSlave->parameters();
- //aSlave->setParameters(aMaster->parameters());
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(aRelated);
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
- //// Remove slave's parameters
- //std::list<ParameterWrapperPtr>::iterator aParIt = aSlaveParams.begin();
- //for (; aParIt != aSlaveParams.end(); ++aParIt)
- // remove(*aParIt);
+ static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
+ std::shared_ptr<GeomAPI_Pnt2d> aCenter(
+ new GeomAPI_Pnt2d(*anArc->center.x, *anArc->center.y));
+ std::shared_ptr<GeomAPI_Pnt2d> aStart(
+ new GeomAPI_Pnt2d(*anArc->start.x, *anArc->start.y));
- aMasterFound->second.insert(aSlave);
- }
-}
+ *anArc->rad = aStart->distance(aCenter);
+ std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(aStart->xy()->decreased(aCenter->xy())));
+ *anArc->startAngle = OX->angle(aDir);
-void PlaneGCSSolver_Storage::changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup)
-{
- theEntity->setGroup(theGroup);
- if (theGroup == myGroupID)
- makeVariable(theEntity);
- else {
- if (theEntity->type() == ENTITY_POINT)
- update(theEntity);
- makeConstant(theEntity);
+ aDir = std::shared_ptr<GeomAPI_Dir2d>(
+ new GeomAPI_Dir2d((*anArc->end.x) - aCenter->x(), (*anArc->end.y) - aCenter->y()));
+ *anArc->endAngle = OX->angle(aDir);
}
-}
-void PlaneGCSSolver_Storage::changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup)
-{
- // TODO
+ return isUpdated;
}
-void PlaneGCSSolver_Storage::verifyFixed()
+bool PlaneGCSSolver_Storage::update(AttributePtr theAttribute, bool theForce)
{
- // TODO
-}
+ if (!theAttribute->isInitialized())
+ return false;
-void PlaneGCSSolver_Storage::processArc(const EntityWrapperPtr& theArc)
-{
- // Calculate additional parameters necessary for PlaneGCS
- const std::list<EntityWrapperPtr>& aSubs = theArc->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
- bool isFixed[3] = {false, false, false};
- for (int i = 0; (*aSubIt)->type() == ENTITY_POINT; ++i) { // search scalar entities
- isFixed[i] = (*aSubIt)->group() == GID_OUTOFGROUP;
- ++aSubIt;
+ AttributePtr anAttribute = theAttribute;
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
+ if (aRefAttr) {
+ if (aRefAttr->isObject()) {
+ FeaturePtr aFeature;
+ /// TODO: Check resultToFeatureOrAttribute() precisely.
+ resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
+ if (aFeature)
+ return update(aFeature, theForce);
+ } else
+ anAttribute = aRefAttr->attr();
}
- double* aStartAngle =
- std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
- double* aEndAngle =
- std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt++)->scalar();
- double* aRadius = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(*aSubIt)->scalar();
-
- std::shared_ptr<SketchPlugin_Feature> anArcFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(theArc->baseFeature());
- std::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- anArcFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aStartAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- anArcFeature->attribute(SketchPlugin_Arc::START_ID()));
- std::shared_ptr<GeomDataAPI_Point2D> aEndAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
- anArcFeature->attribute(SketchPlugin_Arc::END_ID()));
- if (!aCenterAttr || !aStartAttr || !aEndAttr)
- return;
- std::shared_ptr<GeomAPI_Pnt2d> aCenterPnt = aCenterAttr->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aStartPnt = aStartAttr->pnt();
- std::shared_ptr<GeomAPI_Pnt2d> aEndPnt = aEndAttr->pnt();
-
- if (isFixed[2] && !isFixed[1])
- *aRadius = aCenterPnt->distance(aEndPnt);
- else
- *aRadius = aCenterPnt->distance(aStartPnt);
- if (!anArcFeature->lastResult())
- return;
- static std::shared_ptr<GeomAPI_Dir2d> OX(new GeomAPI_Dir2d(1.0, 0.0));
- std::shared_ptr<GeomAPI_Dir2d> aDir(new GeomAPI_Dir2d(
- aStartPnt->xy()->decreased(aCenterPnt->xy())));
- *aStartAngle = OX->angle(aDir);
- aDir = std::shared_ptr<GeomAPI_Dir2d>(new GeomAPI_Dir2d(
- aEndPnt->xy()->decreased(aCenterPnt->xy())));
- *aEndAngle = OX->angle(aDir);
-
- // no need to constraint a fixed or a copied arc
- if (theArc->group() == GID_OUTOFGROUP || anArcFeature->isCopy())
- return;
- // No need to add constraints if they are already exist
- std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
- aFound = myArcConstraintMap.find(theArc);
-// if (aFound != myArcConstraintMap.end())
-// return;
-
- // Prepare additional constraints to produce the arc
- std::vector<GCSConstraintPtr> anArcConstraints;
- std::shared_ptr<PlaneGCSSolver_EntityWrapper> anArcEnt =
- std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theArc);
- std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anArcEnt->entity());
- // Distances from center till start and end points are equal to radius
- GCSConstraintPtr aNew = GCSConstraintPtr(new GCS::ConstraintP2PDistance(
- anArc->center, anArc->start, anArc->rad));
-// aNew->setTag((int)(++myConstraintLastID));
- anArcConstraints.push_back(aNew);
- aNew = GCSConstraintPtr(new GCS::ConstraintP2PDistance(
- anArc->center, anArc->end, anArc->rad));
-// aNew->setTag((int)myConstraintLastID);
- anArcConstraints.push_back(aNew);
- // Angles of start and end points should be equal to given angles
- aNew = GCSConstraintPtr(new GCS::ConstraintP2PAngle(
- anArc->center, anArc->start, anArc->startAngle));
-// aNew->setTag((int)myConstraintLastID);
- anArcConstraints.push_back(aNew);
- aNew = GCSConstraintPtr(new GCS::ConstraintP2PAngle(
- anArc->center, anArc->end, anArc->endAngle));
-// aNew->setTag((int)myConstraintLastID);
- anArcConstraints.push_back(aNew);
-
- myArcConstraintMap[theArc] = anArcConstraints;
-}
+ EntityWrapperPtr aRelated = entity(anAttribute);
+ if (!aRelated) { // Attribute does not exist, create it.
+ // First of all check if the parent feature exists. If not, add it.
+ FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
+ if (aFeature && myFeatureMap.find(aFeature) == myFeatureMap.end())
+ return update(aFeature, theForce); // theAttribute has been processed while adding feature
-void PlaneGCSSolver_Storage::makeConstant(const EntityWrapperPtr& theEntity)
-{
- toggleEntity(theEntity, myParameters, myConst);
- if (theEntity->type() == ENTITY_POINT)
- updateCoincident(theEntity);
+ PlaneGCSSolver_AttributeBuilder aBuilder(this);
+ aRelated = createAttribute(anAttribute, &aBuilder);
+ return aRelated.get() != 0;
+ }
+
+ bool isUpdated = updateValues(anAttribute, aRelated);
+ if (isUpdated)
+ setNeedToResolve(true);
+ return isUpdated;
}
-void PlaneGCSSolver_Storage::makeVariable(const EntityWrapperPtr& theEntity)
+
+
+bool PlaneGCSSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
{
- toggleEntity(theEntity, myConst, myParameters);
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::iterator
+ aFound = myConstraintMap.find(theConstraint);
+ if (aFound != myConstraintMap.end()) {
+ ConstraintID anID = aFound->second->id();
+ // Remove solver's constraints
+ std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
+ std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(mySketchSolver);
+ aSolver->removeConstraint(anID);
+ // Remove constraint
+ myConstraintMap.erase(aFound);
+
+ // notify subscibers
+ notify(theConstraint);
+ }
+ return true;
}
-static void getParametersToMove(const EntityWrapperPtr& theEntity, std::set<double*>& theParamList)
+void PlaneGCSSolver_Storage::removeInvalidEntities()
{
- const std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
- std::list<ParameterWrapperPtr>::const_iterator aPIt = aParams.begin();
- for (; aPIt != aParams.end(); ++aPIt)
- theParamList.insert(
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(*aPIt)->parameter());
-
- const std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
-
- if (theEntity->type() == ENTITY_ARC) {
- // workaround for the arc processing, because the arc is fixed by a set of constraints,
- // which will conflict with all parameters fixed:
- // 1. take center
- getParametersToMove(*aSIt++, theParamList);
- // 2. skip start and end points
- ++aSIt;
- // 3. take radius, start angle and end angle parameters
- getParametersToMove(*(++aSIt), theParamList);
- getParametersToMove(*(++aSIt), theParamList);
- getParametersToMove(*(++aSIt), theParamList);
- } else {
- for (; aSIt != aSubs.end(); ++aSIt)
- getParametersToMove(*aSIt, theParamList);
+ PlaneGCSSolver_EntityDestroyer aDestroyer;
+
+ // Remove invalid constraints
+ std::list<ConstraintPtr> anInvalidConstraints;
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
+ aCIter = myConstraintMap.begin();
+ for (; aCIter != myConstraintMap.end(); ++aCIter)
+ if (!aCIter->first->data() || !aCIter->first->data()->isValid())
+ anInvalidConstraints.push_back(aCIter->first);
+ std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
+ for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
+ removeConstraint(*anInvCIt);
+
+ // Remove invalid features
+ std::list<FeaturePtr> anInvalidFeatures;
+ std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
+ for (; aFIter != myFeatureMap.end(); aFIter++)
+ if (!aFIter->first->data() || !aFIter->first->data()->isValid()) {
+ anInvalidFeatures.push_back(aFIter->first);
+ aDestroyer.remove(aFIter->second);
+
+ // remove invalid arc
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr>::iterator
+ aFound = myArcConstraintMap.find(aFIter->second);
+ if (aFound != myArcConstraintMap.end()) {
+ std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(
+ mySketchSolver)->removeConstraint(aFound->second->id());
+ myArcConstraintMap.erase(aFound);
+ }
+ }
+ std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
+ for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
+ removeFeature(*anInvFIt);
+
+ // Remove invalid attributes
+ std::list<AttributePtr> anInvalidAttributes;
+ std::map<AttributePtr, EntityWrapperPtr>::const_iterator anAttrIt = myAttributeMap.begin();
+ for (; anAttrIt != myAttributeMap.end(); ++anAttrIt) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature(anAttrIt->first->owner());
+ if (!anOwner || !anOwner->data() || !anOwner->data()->isValid()) {
+ anInvalidAttributes.push_back(anAttrIt->first);
+ aDestroyer.remove(anAttrIt->second);
+ }
}
+ std::list<AttributePtr>::const_iterator anInvAtIt = anInvalidAttributes.begin();
+ for (; anInvAtIt != anInvalidAttributes.end(); ++anInvAtIt)
+ removeAttribute(*anInvAtIt);
+
+ // free memory occupied by parameters
+ removeParameters(aDestroyer.parametersToRemove());
+
+ /// TODO: Think on optimization of checking invalid features and attributes
}
-void PlaneGCSSolver_Storage::toggleEntity(
- const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo)
-{
- std::set<double*> aParamsToMove;
- getParametersToMove(theEntity, aParamsToMove);
- GCS::VEC_pD::iterator anIt = theFrom.begin();
- while (anIt != theFrom.end()) {
- if (aParamsToMove.find(*anIt) == aParamsToMove.end()) {
- ++anIt;
- continue;
- }
- theTo.push_back(*anIt);
- int aShift = int(anIt - theFrom.begin());
- theFrom.erase(anIt);
- anIt = theFrom.begin() + aShift;
- }
+double* PlaneGCSSolver_Storage::createParameter()
+{
+ double* aResult = new double(0);
+ myParameters.push_back(aResult);
+ return aResult;
}
-void PlaneGCSSolver_Storage::updateCoincident(const EntityWrapperPtr& thePoint)
+void PlaneGCSSolver_Storage::removeParameters(const GCS::SET_pD& theParams)
{
- CoincidentPointsMap::iterator anIt = myCoincidentPoints.begin();
- for (; anIt != myCoincidentPoints.end(); ++anIt) {
- if (anIt->first == thePoint || anIt->second.find(thePoint) != anIt->second.end()) {
- std::set<EntityWrapperPtr> aCoincident = anIt->second;
- aCoincident.insert(anIt->first);
-
- const std::list<ParameterWrapperPtr>& aBaseParams = thePoint->parameters();
- std::list<ParameterWrapperPtr> aParams;
- std::list<ParameterWrapperPtr>::const_iterator aBaseIt, anUpdIt;
-
- std::set<EntityWrapperPtr>::const_iterator aCoincIt = aCoincident.begin();
- for (; aCoincIt != aCoincident.end(); ++aCoincIt)
- if (*aCoincIt != thePoint && (*aCoincIt)->group() != GID_OUTOFGROUP) {
- aParams = (*aCoincIt)->parameters();
- aBaseIt = aBaseParams.begin();
- for (anUpdIt = aParams.begin(); anUpdIt != aParams.end(); ++anUpdIt, ++aBaseIt)
- (*anUpdIt)->setValue((*aBaseIt)->value());
- }
-
- break;
- }
- }
+ for (int i = (int)myParameters.size() - 1; i >= 0; --i)
+ if (theParams.find(myParameters[i]) != theParams.end())
+ myParameters.erase(myParameters.begin() + i);
}
return false;
}
-void PlaneGCSSolver_Storage::initializeSolver(SolverPtr theSolver)
+void PlaneGCSSolver_Storage::initializeSolver()
{
std::shared_ptr<PlaneGCSSolver_Solver> aSolver =
- std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(theSolver);
- if (!aSolver)
- return;
- aSolver->clear();
-
- if (myExistArc)
- processArcs();
-
- // initialize constraints
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- GCS::SET_I aTangentIDs;
- std::list<std::set<double*> > aCoincidentPoints;
- for (; aCIt != myConstraintMap.end(); ++aCIt) {
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt = aCIt->second.begin();
- for (; aCWIt != aCIt->second.end(); ++ aCWIt) {
- std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aGCS =
- std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(*aCWIt);
- std::list<GCSConstraintPtr>::const_iterator anIt = aGCS->constraints().begin();
- for (; anIt != aGCS->constraints().end(); ++anIt)
- if (!isRedundant(*anIt, aGCS, aCoincidentPoints))
- aSolver->addConstraint(*anIt, aGCS->type());
- }
- // store IDs of tangent constraints to avoid incorrect report of redundant constraints
- if (aCIt->first && aCIt->first->getKind() == SketchPlugin_ConstraintTangent::ID())
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++ aCWIt)
- aTangentIDs.insert((int)(*aCWIt)->id());
- }
- // additional constraints for arcs
- std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >::const_iterator
- anArcIt = myArcConstraintMap.begin();
- for (; anArcIt != myArcConstraintMap.end(); ++anArcIt) {
- std::vector<GCSConstraintPtr>::const_iterator anIt = anArcIt->second.begin();
- for (; anIt != anArcIt->second.end(); ++anIt)
- aSolver->addConstraint(*anIt, CONSTRAINT_UNKNOWN);
- }
- // removed waste constraints
- std::list<GCSConstraintPtr>::const_iterator aRemIt = myRemovedConstraints.begin();
- for (; aRemIt != myRemovedConstraints.end(); ++aRemIt)
- aSolver->removeConstraint(*aRemIt);
- myRemovedConstraints.clear();
- // set list of tangent constraints
- aSolver->setTangent(aTangentIDs);
- // initialize unknowns
- aSolver->setParameters(myParameters);
+ std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(mySketchSolver);
+ if (aSolver)
+ aSolver->setParameters(myParameters);
}
// indicates attribute containing in the external feature
return aSketchFeature.get() && aSketchFeature->isExternal();
}
-void PlaneGCSSolver_Storage::refresh(bool theFixedOnly) const
+void PlaneGCSSolver_Storage::refresh() const
{
- //blockEvents(true);
-
const double aTol = 1000. * tolerance; // tolerance to prevent frequent updates
std::map<AttributePtr, EntityWrapperPtr>::const_iterator anIt = myAttributeMap.begin();
- std::list<ParameterWrapperPtr> aParams;
- std::list<ParameterWrapperPtr>::const_iterator aParIt;
for (; anIt != myAttributeMap.end(); ++anIt) {
// the external feature always should keep the up to date values, so,
// refresh from the solver is never needed
- bool isExternal = isExternalAttribute(anIt->first);
-
- // update parameter wrappers and obtain values of attributes
- aParams = anIt->second->parameters();
- double aCoords[3];
- bool isUpd[3] = {false};
- int i = 0;
- for (aParIt = aParams.begin(); i < 3 && aParIt != aParams.end(); ++aParIt, ++i) {
- if (!theFixedOnly || isExternal ||
- (*aParIt)->group() == GID_OUTOFGROUP || (*aParIt)->isParametric()) {
- aCoords[i] = (*aParIt)->value();
- isUpd[i] = true;
- }
- }
- if (!isUpd[0] && !isUpd[1] && !isUpd[2])
- continue; // nothing is updated
+ if (isExternalAttribute(anIt->first))
+ continue;
std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anIt->first);
if (aPoint2D) {
- if ((isUpd[0] && fabs(aPoint2D->x() - aCoords[0]) > aTol) ||
- (isUpd[1] && fabs(aPoint2D->y() - aCoords[1]) > aTol) || isExternal) {
- // Find points coincident with this one (probably not in GID_OUTOFGROUP)
- CoincidentPointsMap::const_iterator aCoincIt = myCoincidentPoints.begin();
- for (; aCoincIt != myCoincidentPoints.end(); ++aCoincIt)
- if (aCoincIt->first == anIt->second ||
- aCoincIt->second.find(anIt->second) != aCoincIt->second.end())
- break;
- // get coordinates of "master"-point
- std::shared_ptr<GeomDataAPI_Point2D> aMaster = aCoincIt != myCoincidentPoints.end() ?
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aCoincIt->first->baseAttribute()) :
- aPoint2D;
- if (!isUpd[0] || isExternal) aCoords[0] = aMaster->x();
- if (!isUpd[1] || isExternal) aCoords[1] = aMaster->y();
- if (!isExternal)
- aPoint2D->setValue(aCoords[0], aCoords[1]);
- if (aCoincIt != myCoincidentPoints.end()) {
- if (aMaster && !isExternalAttribute(aMaster))
- aMaster->setValue(aCoords[0], aCoords[1]);
- std::set<EntityWrapperPtr>::const_iterator aSlaveIt = aCoincIt->second.begin();
- for (; aSlaveIt != aCoincIt->second.end(); ++aSlaveIt) {
- aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSlaveIt)->baseAttribute());
- if (aPoint2D && !isExternalAttribute(aPoint2D))
- aPoint2D->setValue(aCoords[0], aCoords[1]);
- }
- }
- }
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPointWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->second);
+ GCSPointPtr aGCSPoint = aPointWrapper->point();
+ if (fabs(aPoint2D->x() - (*aGCSPoint->x)) > aTol ||
+ fabs(aPoint2D->y() - (*aGCSPoint->y)) > aTol)
+ aPoint2D->setValue(*aGCSPoint->x, *aGCSPoint->y);
continue;
}
AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anIt->first);
- if (aScalar && !isExternal) {
- if (isUpd[0] && fabs(aScalar->value() - aCoords[0]) > aTol)
- aScalar->setValue(aCoords[0]);
+ if (aScalar) {
+ ScalarWrapperPtr aScalarWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anIt->second);
+ if (fabs(aScalar->value() - aScalarWrapper->value()) > aTol)
+ aScalar->setValue(aScalarWrapper->value());
continue;
}
}
-
- //blockEvents(false);
-}
-
-EntityWrapperPtr PlaneGCSSolver_Storage::calculateMiddlePoint(
- EntityWrapperPtr theBase, double theCoeff)
-{
- std::shared_ptr<PlaneGCSSolver_Builder> aBuilder =
- std::dynamic_pointer_cast<PlaneGCSSolver_Builder>(PlaneGCSSolver_Builder::getInstance());
-
- std::shared_ptr<GeomAPI_XY> aMidPoint;
- if (theBase->type() == ENTITY_LINE) {
- std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
- const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (int i = 0; i < 2; ++i, ++anIt)
- aPoints[i] = aBuilder->point(*anIt);
- aMidPoint = aPoints[0]->xy()->multiplied(1.0 - theCoeff)->added(
- aPoints[1]->xy()->multiplied(theCoeff));
- }
- else if (theBase->type() == ENTITY_ARC) {
- double theX, theY;
- double anArcPoint[3][2];
- const std::list<EntityWrapperPtr>& aSubs = theBase->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (int i = 0; i < 3; ++i, ++anIt) {
- std::shared_ptr<GeomAPI_Pnt2d> aPoint = aBuilder->point(*anIt);
- anArcPoint[i][0] = aPoint->x();
- anArcPoint[i][1] = aPoint->y();
- }
- // project last point of arc on the arc
- double x = anArcPoint[1][0] - anArcPoint[0][0];
- double y = anArcPoint[1][1] - anArcPoint[0][1];
- double aRad = sqrt(x*x + y*y);
- x = anArcPoint[2][0] - anArcPoint[0][0];
- y = anArcPoint[2][1] - anArcPoint[0][1];
- double aNorm = sqrt(x*x + y*y);
- if (aNorm >= tolerance) {
- anArcPoint[2][0] = x * aRad / aNorm;
- anArcPoint[2][1] = y * aRad / aNorm;
- }
- anArcPoint[1][0] -= anArcPoint[0][0];
- anArcPoint[1][1] -= anArcPoint[0][1];
- if (theCoeff < tolerance) {
- theX = anArcPoint[0][0] + anArcPoint[1][0];
- theY = anArcPoint[0][1] + anArcPoint[1][1];
- } else if (1 - theCoeff < tolerance) {
- theX = anArcPoint[0][0] + anArcPoint[2][0];
- theY = anArcPoint[0][1] + anArcPoint[2][1];
- } else {
- std::shared_ptr<GeomAPI_Dir2d>
- aStartDir(new GeomAPI_Dir2d(anArcPoint[1][0], anArcPoint[1][1]));
- std::shared_ptr<GeomAPI_Dir2d>
- aEndDir(new GeomAPI_Dir2d(anArcPoint[2][0], anArcPoint[2][1]));
- double anAngle = aStartDir->angle(aEndDir);
- if (anAngle < 0)
- anAngle += 2.0 * PI;
- anAngle *= theCoeff;
- double aCos = cos(anAngle);
- double aSin = sin(anAngle);
- theX = anArcPoint[0][0] + anArcPoint[1][0] * aCos - anArcPoint[1][1] * aSin;
- theY = anArcPoint[0][1] + anArcPoint[1][0] * aSin + anArcPoint[1][1] * aCos;
- }
- aMidPoint = std::shared_ptr<GeomAPI_XY>(new GeomAPI_XY(theX, theY));
- }
-
- if (!aMidPoint)
- return EntityWrapperPtr();
-
- std::list<ParameterWrapperPtr> aParameters;
- aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->x()));
- aParameters.push_back(aBuilder->createParameter(myGroupID, aMidPoint->y()));
- // Create entity (parameters are not filled)
- GCSPointPtr aPnt(new GCS::Point);
- aPnt->x =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.front())->parameter();
- aPnt->y =
- std::dynamic_pointer_cast<PlaneGCSSolver_ParameterWrapper>(aParameters.back())->parameter();
-
- EntityWrapperPtr aResult(new PlaneGCSSolver_PointWrapper(AttributePtr(), aPnt));
- aResult->setGroup(myGroupID);
- aResult->setParameters(aParameters);
-
- update(aResult);
- return aResult;
}
#include <SketchSolver_Storage.h>
#include <SketchSolver_ISolver.h>
+class PlaneGCSSolver_EntityBuilder;
+
/** \class PlaneGCSSolver_Storage
* \ingroup Plugins
* \brief Contains all necessary data in PlaneGCS format to solve a single group of constraints
class PlaneGCSSolver_Storage : public SketchSolver_Storage
{
public:
- PlaneGCSSolver_Storage(const GroupID& theGroup);
+ PlaneGCSSolver_Storage(const SolverPtr& theSolver);
// ============= Inherited from SketchSolver_Storage =============
/// \brief Change mapping between constraint from SketchPlugin and
- /// the list of constraints applicable for corresponding solver.
- /// Derived here to update point-point coincidence.
- /// \param theConstraint [in] original SketchPlugin constraint
- /// \param theSolverConstraints [in] list of solver's constraints
- virtual void addConstraint(ConstraintPtr theConstraint,
- std::list<ConstraintWrapperPtr> theSolverConstraints);
-
- /// \brief Update constraint's data
- /// \return \c true if any value is updated
- virtual bool update(ConstraintWrapperPtr theConstraint);
- /// \brief Update entity's data
- /// \return \c true if any value is updated
- virtual bool update(EntityWrapperPtr theEntity);
- /// \brief Update parameter's data
- /// \return \c true if the value of parameter is updated
- virtual bool update(ParameterWrapperPtr theParameter);
-
- /// \brief Update SketchPlugin features after resolving constraints
- /// \param theFixedOnly [in] if \c true the fixed points will be updated only
- virtual void refresh(bool theFixedOnly = false) const;
+ /// a constraint applicable for corresponding solver.
+ /// \param theConstraint [in] original SketchPlugin constraint
+ /// \param theSolverConstraint [in] solver's constraint
+ virtual void addConstraint(ConstraintPtr theConstraint,
+ ConstraintWrapperPtr theSolverConstraint) override;
- /// \brief Check if some parameters or entities are returned
- /// to the current group after removing temporary constraints
- virtual void verifyFixed();
+ /// \brief Add list of temporary constraints which will be destroyed
+ /// after the next solving of the set of constraints.
+ /// \param theSolverConstraint [in] solver's constraint
+ virtual void addTemporaryConstraint(const ConstraintWrapperPtr& theSolverConstraint) override;
- /// \brief Mark two points as coincident
- virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave);
- /// \brief Shows the storage has the same constraint twice
- virtual bool hasDuplicatedConstraint() const
- { return false; }
+ /// \brief Convert feature to the form applicable for specific solver and map it
+ /// \param theFeature [in] feature to convert
+ /// \param theForce [in] forced feature creation
+ /// \return \c true if the feature has been created or updated
+ virtual bool update(FeaturePtr theFeature, bool theForce = false) override;
- /// \brief Calculate point on theBase entity. Value theCoeff is in [0.0 .. 1.0] and
- /// shows the distance from the start point.
- virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase, double theCoeff);
+ /// \brief Convert attribute to the form applicable for specific solver and map it
+ /// \param theAttribute [in] attribute to convert
+ /// \param theForce [in] forced feature creation
+ /// \return \c true if the attribute has been created or updated
+ virtual bool update(AttributePtr theAttribute, bool theForce = false) override;
- /// \brief Initialize solver by constraints, entities and parameters
- virtual void initializeSolver(SolverPtr theSolver);
-protected:
- /// \brief Remove constraint
+ /// \brief Removes constraint from the storage
/// \return \c true if the constraint and all its parameters are removed successfully
- virtual bool remove(ConstraintWrapperPtr theConstraint);
- /// \brief Remove entity
- /// \return \c true if the entity and all its parameters are removed successfully
- virtual bool remove(EntityWrapperPtr theEntity);
- /// \brief Remove parameter
- /// \return \c true if the parameter has been removed
- virtual bool remove(ParameterWrapperPtr theParameter);
+ virtual bool removeConstraint(ConstraintPtr theConstraint) override;
- /// \brief Update the group for the given entity, its sub-entities and parameters
- virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup);
- /// \brief Update the group for the given parameter
- virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup);
+ /// \brief Update SketchPlugin features after resolving constraints
+ virtual void refresh() const override;
+ /// \brief Initialize solver by constraints, entities and parameters
+ virtual void initializeSolver();
-// ============= Own methods =============
+ /// \brief Initialize memory for new solver's parameter
+ double* createParameter();
+ /// \brief Release memory occupied by parameters
+ void removeParameters(const GCS::SET_pD& theParams);
- /// \brief Move parameters of the entity to the constants
- void makeConstant(const EntityWrapperPtr& theEntity);
- /// \brief Move parameters of the entity to the variables
- void makeVariable(const EntityWrapperPtr& theEntity);
+ /// \brief Remove all features became invalid
+ virtual void removeInvalidEntities() override;
private:
- /// \brief Move parameters of the entity from the list of variables to the list of constants
- /// and vice versa
- /// \param theEntity [in] entity to be changed
- /// \param theFrom [out] source list
- /// \param theTo [out] destination list
- void toggleEntity(const EntityWrapperPtr& theEntity, GCS::VEC_pD& theFrom, GCS::VEC_pD& theTo);
-
- /// \brief Create additional constraints for correct processing of arcs
- /// \param theArc [in] updated arc
- void processArc(const EntityWrapperPtr& theArc);
-
- /// \brief Adjust parameters of points coincident with the given
- void updateCoincident(const EntityWrapperPtr& thePoint);
-
/// \brief Verifies the constraint should not be added into the solver
///
/// This is a workaround method to avoid some kinds of conflicting constraints:
ConstraintWrapperPtr theParentConstraint,
std::list<std::set<double*> >& theCoincidentPoints) const;
+ /// \brief Convert feature using specified builder.
+ EntityWrapperPtr createFeature(const FeaturePtr& theFeature,
+ PlaneGCSSolver_EntityBuilder* theBuilder);
+
+ /// \brief Convert attribute using specified builder.
+ EntityWrapperPtr createAttribute(const AttributePtr& theAttribute,
+ PlaneGCSSolver_EntityBuilder* theBuilder);
+
private:
- GCS::VEC_pD myParameters; ///< list of parameters
- GCS::VEC_pD myConst; ///< list of constants
- EntityID myEntityLastID; ///< identifier of last added entity
- ConstraintID myConstraintLastID; ///< identifier of last added constraint
+ GCS::VEC_pD myParameters; ///< list of parameters
+ ConstraintID myConstraintLastID; ///< identifier of last added constraint
/// additional constraints for correct processing of the arcs
- std::map<EntityWrapperPtr, std::vector<GCSConstraintPtr> >
- myArcConstraintMap;
+ std::map<EntityWrapperPtr, ConstraintWrapperPtr> myArcConstraintMap;
/// list of removed constraints to notify solver
- std::list<GCSConstraintPtr> myRemovedConstraints;
+ std::list<GCSConstraintPtr> myRemovedConstraints;
};
#endif
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_Update.h
+// Created: 17 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_Update_H_
+#define PlaneGCSSolver_Update_H_
+
+#include <ModelAPI_Feature.h>
+
+#include <list>
+#include <memory>
+#include <string>
+
+class SketchSolver_Constraint;
+class PlaneGCSSolver_Update;
+typedef std::shared_ptr<PlaneGCSSolver_Update> UpdaterPtr;
+
+/** \class PlaneGCSSolver_Update
+ * \ingroup Plugins
+ * \brief Send events to listeners about changing a feature
+ */
+class PlaneGCSSolver_Update
+{
+public:
+ PlaneGCSSolver_Update(UpdaterPtr theNext = UpdaterPtr())
+ : myNext(theNext)
+ {}
+
+ virtual ~PlaneGCSSolver_Update() {}
+
+ /// \brief Attach listener
+ /// \param theObserver [in] object which want to receive notifications
+ /// \param theType [in] receive notifications about changing objects
+ /// of theType and their derivatives
+ virtual void attach(SketchSolver_Constraint* theObserver, const std::string& theType) = 0;
+
+ /// \brief Detach listener
+ void detach(SketchSolver_Constraint* theObserver) {
+ std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
+ for (; anIt != myObservers.end(); ++anIt)
+ if (*anIt == theObserver) {
+ myObservers.erase(anIt);
+ break;
+ }
+ // detach listener from all senders
+ if (myNext)
+ myNext->detach(theObserver);
+ }
+
+ /// \brief Send notification about update of the feature to all interested
+ virtual void update(const FeaturePtr& theFeature) = 0;
+
+protected:
+ UpdaterPtr myNext; ///< next updater, access if current one unable to process request
+ std::list<SketchSolver_Constraint*> myObservers; ///< list of observers
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_UpdateCoincidence.cpp
+// Created: 17 Feb 2017
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <SketchSolver_Constraint.h>
+
+#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintMiddle.h>
+
+void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver, const std::string& theType)
+{
+ if (theType == GROUP()) {
+ std::list<SketchSolver_Constraint*>::iterator aPlaceToAdd = myObservers.end();
+ // point-point coincidence is placed first
+ if (theObserver->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
+ for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
+ if ((*aPlaceToAdd)->getType() != CONSTRAINT_PT_PT_COINCIDENT)
+ break;
+ }
+ myObservers.insert(aPlaceToAdd, theObserver);
+ } else
+ myNext->attach(theObserver, theType);
+}
+
+void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
+{
+ if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
+ theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
+ myCoincident.clear();
+ // notify listeners and stop procesing
+ std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
+ for (; anIt != myObservers.end(); ++anIt)
+ (*anIt)->notify(theFeature, this);
+ } else
+ myNext->update(theFeature);
+}
+
+bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
+ const EntityWrapperPtr& theEntity1,
+ const EntityWrapperPtr& theEntity2)
+{
+ bool isAccepted = true;
+
+ std::list<std::set<EntityWrapperPtr> >::iterator anIt = myCoincident.begin();
+ std::list<std::set<EntityWrapperPtr> >::iterator aFound1 = myCoincident.end();
+ std::list<std::set<EntityWrapperPtr> >::iterator aFound2 = myCoincident.end();
+ for (; anIt != myCoincident.end(); ++anIt) {
+ if (aFound1 == myCoincident.end() && anIt->find(theEntity1) != anIt->end())
+ aFound1 = anIt;
+ if (aFound2 == myCoincident.end() && anIt->find(theEntity2) != anIt->end())
+ aFound2 = anIt;
+ if (aFound1 != myCoincident.end() && aFound2 != myCoincident.end())
+ break;
+ }
+
+ if (aFound1 == myCoincident.end() && aFound2 == myCoincident.end()) {
+ // new group of coincidence
+ std::set<EntityWrapperPtr> aNewCoinc;
+ aNewCoinc.insert(theEntity1);
+ aNewCoinc.insert(theEntity2);
+ myCoincident.push_back(aNewCoinc);
+ } else if (aFound1 == aFound2) // same group => already coincident
+ isAccepted = false;
+ else if (aFound1 == myCoincident.end())
+ aFound2->insert(theEntity1);
+ else if (aFound2 == myCoincident.end())
+ aFound1->insert(theEntity2);
+ else { // merge two groups
+ aFound1->insert(aFound2->begin(), aFound2->end());
+ myCoincident.erase(aFound2);
+ }
+
+ return isAccepted;
+}
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_UpdateCoincidence.h
+// Created: 17 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_UpdateCoincidence_H_
+#define PlaneGCSSolver_UpdateCoincidence_H_
+
+#include <PlaneGCSSolver_Update.h>
+#include <SketchSolver_IEntityWrapper.h>
+
+/** \class PlaneGCSSolver_UpdateCoincidence
+ * \ingroup Plugins
+ * \brief Send events to listeners about changing a constraint
+ */
+class PlaneGCSSolver_UpdateCoincidence : public PlaneGCSSolver_Update
+{
+public:
+ PlaneGCSSolver_UpdateCoincidence(UpdaterPtr theNext = UpdaterPtr())
+ : PlaneGCSSolver_Update(theNext)
+ {}
+
+ virtual ~PlaneGCSSolver_UpdateCoincidence() {}
+
+ /// \brief Group of entities, processed by this kind of updater
+ static const std::string& GROUP()
+ {
+ static const std::string TYPE("Coincidence");
+ return TYPE;
+ }
+
+ /// \brief Attach listener
+ /// \param theObserver [in] object which want to receive notifications
+ /// \param theType [in] receive notifications about changing objects
+ /// of theType and their derivatives
+ virtual void attach(SketchSolver_Constraint* theObserver, const std::string& theType) override;
+
+ /// \brief Send notification about update of the feature to all interested
+ virtual void update(const FeaturePtr& theFeature) override;
+
+ /// \brief Verifies the entities are not coincident yet
+ /// \return \c true if the entities does not coincident
+ bool checkCoincidence(const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2);
+
+private:
+ std::list<std::set<EntityWrapperPtr> > myCoincident; ///< list of coincidences
+};
+
+#endif
--- /dev/null
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_UpdateFeature.cpp
+// Created: 17 Feb 2017
+// Author: Artem ZHIDKOV
+
+#include <PlaneGCSSolver_UpdateFeature.h>
+#include <SketchSolver_Constraint.h>
+
+void PlaneGCSSolver_UpdateFeature::attach(SketchSolver_Constraint* theObserver, const std::string& theType)
+{
+ if (theType == GROUP())
+ myObservers.push_back(theObserver);
+ else
+ myNext->attach(theObserver, theType);
+}
+
+void PlaneGCSSolver_UpdateFeature::update(const FeaturePtr& theFeature)
+{
+ std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
+ for (; anIt != myObservers.end(); ++anIt)
+ (*anIt)->notify(theFeature, this);
+}
--- /dev/null
+// Copyright (C) 2017-20xx CEA/DEN, EDF R&D
+
+// File: PlaneGCSSolver_UpdateFeature.h
+// Created: 17 Feb 2017
+// Author: Artem ZHIDKOV
+
+#ifndef PlaneGCSSolver_UpdateFeature_H_
+#define PlaneGCSSolver_UpdateFeature_H_
+
+#include <PlaneGCSSolver_Update.h>
+
+/** \class PlaneGCSSolver_UpdateFeature
+ * \ingroup Plugins
+ * \brief Send events to listeners about changing a feature
+ */
+class PlaneGCSSolver_UpdateFeature : public PlaneGCSSolver_Update
+{
+public:
+ PlaneGCSSolver_UpdateFeature(UpdaterPtr theNext = UpdaterPtr())
+ : PlaneGCSSolver_Update(theNext)
+ {}
+
+ /// \brief Group of entities, processed by this kind of updater
+ static const std::string& GROUP()
+ {
+ static const std::string TYPE("Feature");
+ return TYPE;
+ }
+
+ /// \brief Attach listener
+ /// \param theObserver [in] object which want to receive notifications
+ /// \param theType [in] receive notifications about changing objects
+ /// of theType and their derivatives
+ virtual void attach(SketchSolver_Constraint* theObserver, const std::string& theType) override;
+
+ /// \brief Send notification about update of the feature to all interested
+ virtual void update(const FeaturePtr& theFeature) override;
+};
+
+#endif
#include <stdlib.h>
-#if defined SKETCHSOLVER_EXPORTS
-#if defined WIN32
-#define SKETCHSOLVER_EXPORT __declspec( dllexport )
-#else
-#define SKETCHSOLVER_EXPORT
-#endif
-#else
-#if defined WIN32
-#define SKETCHSOLVER_EXPORT __declspec( dllimport )
-#else
-#define SKETCHSOLVER_EXPORT
-#endif
-#endif
-
/// Tolerance for value of parameters
const double tolerance = 1.e-10;
#define PI 3.1415926535897932
// Types for data entities enumeration
-typedef size_t GroupID;
-typedef size_t ParameterID;
-typedef size_t EntityID;
-typedef size_t ConstraintID;
+typedef int ConstraintID;
// Predefined values for identifiers
-const GroupID GID_UNKNOWN = 0;
-const GroupID GID_OUTOFGROUP = 1;
-
-const ParameterID PID_UNKNOWN = 0;
-const EntityID EID_UNKNOWN = 0;
-const EntityID EID_SKETCH = 1;
-const ConstraintID CID_UNKNOWN = 0;
+const ConstraintID CID_UNKNOWN = 0;
+const ConstraintID CID_MOVEMENT = -1;
#endif
#include <SketchSolver_ConstraintDistance.h>
#include <SketchSolver_ConstraintEqual.h>
#include <SketchSolver_ConstraintFixed.h>
-#include <SketchSolver_ConstraintFixedArcRadius.h>
#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_ConstraintMiddle.h>
#include <SketchSolver_ConstraintMirror.h>
#include <SketchSolver_ConstraintTangent.h>
#include <SketchSolver_ConstraintMultiRotation.h>
#include <SketchSolver_ConstraintMultiTranslation.h>
-#include <SketchSolver_ConstraintMovement.h>
#ifdef _DEBUG
#include <Events_InfoMessage.h>
#include <SketchPlugin_MultiRotation.h>
#include <SketchPlugin_MultiTranslation.h>
-#include <math.h>
+#include <cmath>
SolverConstraintPtr SketchSolver_Builder::createConstraint(ConstraintPtr theConstraint) const
{
SolverConstraintPtr aResult;
DataPtr aData = theConstraint->data();
- if (!aData || !aData->isValid())
- return aResult;
#ifdef _DEBUG
// Verify attributes of constraint and generate errors
return SolverConstraintPtr(new SketchSolver_Constraint(theConstraint));
}
-SolverConstraintPtr SketchSolver_Builder::createFixedConstraint(FeaturePtr theFixedFeature) const
+SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theMovedFeature) const
{
- DataPtr aData = theFixedFeature->data();
- if (!aData || !aData->isValid())
- return SolverConstraintPtr();
- return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theFixedFeature));
+ return SolverConstraintPtr(new SketchSolver_ConstraintFixed(theMovedFeature));
}
-
-SolverConstraintPtr SketchSolver_Builder::createFixedArcRadiusConstraint(FeaturePtr theArc) const
-{
- DataPtr aData = theArc->data();
- if (!aData || !aData->isValid())
- return SolverConstraintPtr();
- return SolverConstraintPtr(new SketchSolver_ConstraintFixedArcRadius(theArc));
-}
-
-SolverConstraintPtr SketchSolver_Builder::createMovementConstraint(FeaturePtr theFixedFeature) const
-{
- DataPtr aData = theFixedFeature->data();
- if (!aData || !aData->isValid())
- return SolverConstraintPtr();
- return SolverConstraintPtr(new SketchSolver_ConstraintMovement(theFixedFeature));
-}
-
-std::shared_ptr<GeomAPI_Pnt2d> SketchSolver_Builder::point(EntityWrapperPtr theEntity) const
-{
- if (theEntity->type() != ENTITY_POINT)
- return std::shared_ptr<GeomAPI_Pnt2d>();
- if (theEntity->subEntities().size() == 1) // SketchPlugin_Point wrapper
- return point(theEntity->subEntities().front());
-
- double aXY[2];
- std::list<ParameterWrapperPtr> aParams = theEntity->parameters();
- std::list<ParameterWrapperPtr>::const_iterator anIt = aParams.begin();
- for (int i = 0; i < 2 && anIt != aParams.end(); ++i, ++anIt)
- aXY[i] = (*anIt)->value();
- if (anIt != aParams.end())
- return std::shared_ptr<GeomAPI_Pnt2d>();
-
- return std::shared_ptr<GeomAPI_Pnt2d>(new GeomAPI_Pnt2d(aXY[0], aXY[1]));
-}
-
-std::shared_ptr<GeomAPI_Lin2d> SketchSolver_Builder::line(EntityWrapperPtr theEntity) const
-{
- if (theEntity->type() != ENTITY_LINE)
- return std::shared_ptr<GeomAPI_Lin2d>();
-
- std::shared_ptr<GeomAPI_Pnt2d> aPoints[2];
- std::list<EntityWrapperPtr> aSubs = theEntity->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anIt = aSubs.begin();
- for (int i = 0; i < 2 && anIt != aSubs.end(); ++i, ++anIt)
- aPoints[i] = point(*anIt);
- if (anIt != aSubs.end())
- return std::shared_ptr<GeomAPI_Lin2d>();
-
- return std::shared_ptr<GeomAPI_Lin2d>(new GeomAPI_Lin2d(aPoints[0], aPoints[1]));
-}
-
{
public:
/// \brief Creates a storage specific for used solver
- virtual StoragePtr createStorage(const GroupID& theGroup) const = 0;
+ virtual StoragePtr createStorage(const SolverPtr&) const = 0;
/// \brief Creates specific solver
virtual SolverPtr createSolver() const = 0;
/// or returns empty pointer if not all attributes are correct
SolverConstraintPtr createConstraint(ConstraintPtr theConstraint) const;
- /// \brief Creates temporary constraint to fix the placement of the feature
- SolverConstraintPtr createFixedConstraint(FeaturePtr theFixedFeature) const;
-
- /// \brief Creates temporary constraint to fix radius of the arc
- SolverConstraintPtr createFixedArcRadiusConstraint(FeaturePtr theArc) const;
-
/// \brief Creates temporary constraint to fix the feature after movement
- SolverConstraintPtr createMovementConstraint(FeaturePtr theFixedFeature) const;
+ SolverConstraintPtr createMovementConstraint(FeaturePtr theMovedFeature) const;
- /// \brief Creates new constraint(s) using given parameters
+ /// \brief Creates new constraint using given parameters
/// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
/// \param theType [in] type of constraint
/// \param theValue [in] numeric characteristic of constraint
- /// (e.g. distance or radius) if applicable
+ /// (e.g. distance or radius) if applicable
/// \param theEntity1 [in] first attribute of constraint
/// \param theEntity2 [in] second attribute of constraint
/// \param theEntity3 [in] third attribute of constraint
/// \param theEntity4 [in] fourth attribute of constraint
- /// \return Created list of wrappers of constraints applicable for specific solver.
- /// Most of constraint types lead to single constraint, but there are some kind of
- /// constraints (e.g. mirror), which may produce couple of constraints.
- virtual std::list<ConstraintWrapperPtr>
+ /// \return Created wrapper of constraints applicable for specific solver.
+ virtual ConstraintWrapperPtr
createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroup,
- const EntityID& theSketchID,
const SketchSolver_ConstraintType& theType,
- const double& theValue,
+ const EntityWrapperPtr& theValue,
const EntityWrapperPtr& theEntity1,
const EntityWrapperPtr& theEntity2 = EntityWrapperPtr(),
const EntityWrapperPtr& theEntity3 = EntityWrapperPtr(),
/// \brief Creates new multi-translation or multi-rotation constraint
/// \param theConstraint [in] original constraint
- /// \param theGroupID [in] group the constraint belongs to
- /// \param theSketchID [in] sketch the constraint belongs to
/// \param theType [in] type of constraint
/// \param theValue [in] numeric characteristic of constraint (angle for multi-rotation)
/// if applicable
/// \param theFullValue [in] indicates theValue shows full translation delta/rotation angle or
- /// delta/angle between neighbor entities
+ /// delta/angle between neighbor entities
/// \param thePoint1 [in] center for multi-rotation or start point for multi-translation
/// \param thePoint2 [in] end point for multi-translation (empty for multi-rotation)
/// \param theTrsfEnt [in] list of transformed entities
- virtual std::list<ConstraintWrapperPtr>
+ virtual ConstraintWrapperPtr
createConstraint(ConstraintPtr theConstraint,
- const GroupID& theGroup,
- const EntityID& theSketchID,
const SketchSolver_ConstraintType& theType,
- const double& theValue,
+ const EntityWrapperPtr& theValue,
const bool theFullValue,
const EntityWrapperPtr& thePoint1,
const EntityWrapperPtr& thePoint2,
const std::list<EntityWrapperPtr>& theTrsfEnt) const = 0;
- /// \brief Update flags for several kinds of constraints
- virtual void adjustConstraint(ConstraintWrapperPtr theConstraint) const = 0;
-
- /// \brief Creates a feature using list of already created attributes
- /// \param theFeature [in] feature to create
- /// \param theAttributes [in] attributes of the feature
- /// \param theGroupID [in] group the feature belongs to
- /// \param theSketchID [in] sketch the feature belongs to
- /// \return Created wrapper of the feature applicable for specific solver
- virtual EntityWrapperPtr createFeature(FeaturePtr theFeature,
- const std::list<EntityWrapperPtr>& theAttributes,
- const GroupID& theGroupID,
- const EntityID& theSketchID = EID_UNKNOWN) const = 0;
-
- /// \brief Creates an attribute
- /// \param theAttribute [in] attribute to create
- /// \param theGroup [in] group the attribute belongs to
- /// \param theSketchID [in] sketch the attribute belongs to
- /// \return Created wrapper of the attribute applicable for specific solver
- virtual EntityWrapperPtr createAttribute(AttributePtr theAttribute,
- const GroupID& theGroup,
- const EntityID& theSketchID = EID_UNKNOWN) const = 0;
-
/// \brief Convert entity to point
/// \return empty pointer if the entity is not a point
- SKETCHSOLVER_EXPORT std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const;
+ virtual std::shared_ptr<GeomAPI_Pnt2d> point(EntityWrapperPtr theEntity) const = 0;
+ /// \brief Convert entity to line
+ /// \return empty pointer if the entity is not a line
+ virtual std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const = 0;
+
/// \brief Convert entity to line
/// \return empty pointer if the entity is not a line
- SKETCHSOLVER_EXPORT std::shared_ptr<GeomAPI_Lin2d> line(EntityWrapperPtr theEntity) const;
+ virtual std::shared_ptr<GeomAPI_Lin2d> line(FeaturePtr theFeature) const = 0;
/// \brief Check if two connected arcs have centers
/// in same direction relatively to connection point
- SKETCHSOLVER_EXPORT virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
- EntityWrapperPtr theArc2) const { return false; }
+ virtual bool isArcArcTangencyInternal(EntityWrapperPtr theArc1,
+ EntityWrapperPtr theArc2) const = 0;
};
typedef std::shared_ptr<SketchSolver_Builder> BuilderPtr;
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_AttributeBuilder.h>
+
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_Circle.h>
#include <SketchPlugin_Line.h>
SketchSolver_Constraint::SketchSolver_Constraint(
ConstraintPtr theConstraint)
: myBaseConstraint(theConstraint),
- myGroupID(GID_UNKNOWN),
myType(CONSTRAINT_UNKNOWN)
{
}
-void SketchSolver_Constraint::process(StoragePtr theStorage,
- const GroupID& theGroupID,
- const EntityID& theSketchID)
+void SketchSolver_Constraint::process(StoragePtr theStorage, bool theEvensBlocked)
{
myStorage = theStorage;
- myGroupID = theGroupID;
- mySketchID = theSketchID;
+ blockEvents(theEvensBlocked);
// Process constraint according to its type
process();
}
+void SketchSolver_Constraint::blockEvents(bool isBlocked)
+{
+ myBaseConstraint->data()->blockSendAttributeUpdated(isBlocked);
+}
+
SketchSolver_ConstraintType SketchSolver_Constraint::TYPE(ConstraintPtr theConstraint)
{
void SketchSolver_Constraint::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+ if (!myBaseConstraint || !myStorage) {
// Not enough parameters are assigned
return;
}
SketchSolver_ConstraintType aConstrType = getType();
- double aValue;
+ EntityWrapperPtr aValue;
std::vector<EntityWrapperPtr> anAttributes;
getAttributes(aValue, anAttributes);
if (!myErrorMsg.empty())
aConstrType = getType();
BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aNewConstraints = aBuilder->createConstraint(
- myBaseConstraint, myGroupID, mySketchID, aConstrType,
+ ConstraintWrapperPtr aNewConstraint = aBuilder->createConstraint(
+ myBaseConstraint, aConstrType,
aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
- myStorage->addConstraint(myBaseConstraint, aNewConstraints);
+ myStorage->addConstraint(myBaseConstraint, aNewConstraint);
adjustConstraint();
}
void SketchSolver_Constraint::update()
{
cleanErrorMsg();
- std::list<ConstraintWrapperPtr> aWrapper = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::iterator aWIt = aWrapper.begin();
- // Check if attributes of constraint are changed, rebuild constraint
- std::set<AttributePtr> anAttributes;
- std::set<AttributePtr>::iterator aFoundAttr;
- std::set<FeaturePtr> aFeatures;
- std::set<FeaturePtr>::iterator aFoundFeat;
+ // Get list of attributes of the constraint and compare it with previously stored.
+ // If the lists are different, fully rebuild constraint
+ std::set<EntityWrapperPtr> anAttributes;
for (int anEntIndex = 0; anEntIndex < 4; ++anEntIndex) {
AttributePtr anAttr =
myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(anEntIndex));
if (!anAttr)
continue;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
- if (aRefAttr) {
- if (aRefAttr->isObject()) {
- FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
- if (myBaseConstraint->getKind() != SketchPlugin_ConstraintLength::ID())
- aFeatures.insert(aFeat);
- else {
- // Workaround for the Length constraint: add points of line, not line itself
- anAttributes.insert(aFeat->attribute(SketchPlugin_Line::START_ID()));
- anAttributes.insert(aFeat->attribute(SketchPlugin_Line::END_ID()));
- }
- } else
- anAttributes.insert(aRefAttr->attr());
- } else
- anAttributes.insert(anAttr);
- }
- bool hasNewAttr = !(anAttributes.empty() && aFeatures.empty());
- for (; hasNewAttr && aWIt != aWrapper.end(); ++ aWIt) {
- const std::list<EntityWrapperPtr>& aSubs = (*aWIt)->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (; hasNewAttr && aSIt != aSubs.end(); ++aSIt) {
- if ((*aSIt)->baseAttribute()) {
- aFoundAttr = anAttributes.find((*aSIt)->baseAttribute());
- if (aFoundAttr != anAttributes.end())
- anAttributes.erase(aFoundAttr);
- } else {
- aFoundFeat = aFeatures.find((*aSIt)->baseFeature());
- if (aFoundFeat != aFeatures.end())
- aFeatures.erase(aFoundFeat);
+ if (myBaseConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
+ AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
+ FeaturePtr aFeat = ModelAPI_Feature::feature(aRefAttr->object());
+ if (aFeat) {
+ // Workaround for the Length constraint: add points of line, not line itself
+ anAttributes.insert(myStorage->entity(aFeat->attribute(SketchPlugin_Line::START_ID())));
+ anAttributes.insert(myStorage->entity(aFeat->attribute(SketchPlugin_Line::END_ID())));
}
- hasNewAttr = !(anAttributes.empty() && aFeatures.empty());
- }
+ } else
+ anAttributes.insert(myStorage->entity(anAttr));
}
- if (hasNewAttr) {
+
+ std::set<EntityWrapperPtr>::iterator aFound;
+ std::list<EntityWrapperPtr>::const_iterator anAttrIt = myAttributes.begin();
+ for (; anAttrIt != myAttributes.end() && !anAttributes.empty(); ++anAttrIt)
+ anAttributes.erase(*anAttrIt);
+
+ if (!anAttributes.empty()) {
remove();
process();
return;
}
- AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::VALUE()));
- if (aValueAttr) {
- for (aWIt = aWrapper.begin(); aWIt != aWrapper.end(); ++aWIt)
- if (fabs((*aWIt)->value() - aValueAttr->value()) > tolerance) {
- (*aWIt)->setValue(aValueAttr->value());
- myStorage->setNeedToResolve(true);
- }
- }
- myStorage->addConstraint(myBaseConstraint, aWrapper);
+ AttributeDoublePtr aValueAttr = myBaseConstraint->real(SketchPlugin_Constraint::VALUE());
+ if (aValueAttr)
+ myStorage->update(aValueAttr);
adjustConstraint();
}
{
cleanErrorMsg();
myType = CONSTRAINT_UNKNOWN;
+ myStorage->unsubscribeUpdates(this);
return myStorage->removeConstraint(myBaseConstraint);
}
void SketchSolver_Constraint::getAttributes(
- double& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
static const int anInitNbOfAttr = 4;
myType = TYPE(myBaseConstraint);
- AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- aData->attribute(SketchPlugin_Constraint::VALUE()));
- theValue = aValueAttr ? aValueAttr->value() : 0.0;
+ AttributeDoublePtr aValueAttr = aData->real(SketchPlugin_Constraint::VALUE());
+ if (aValueAttr) {
+ PlaneGCSSolver_AttributeBuilder aValueBuilder;
+ theValue = aValueBuilder.createAttribute(aValueAttr);
+ myStorage->addEntity(aValueAttr, theValue);
+ }
int aPtInd = 0; // index of first point in the list of attributes
int aEntInd = 2; // index of first entity in the list of attributes
return;
}
- myStorage->update(*anIter/*, myGroupID*/);
+ myStorage->update(*anIter, true);
EntityWrapperPtr anEntity = myStorage->entity(*anIter);
- if (!anEntity) {
- // Force creation of an entity
- myStorage->update(*anIter, GID_UNKNOWN, true);
- anEntity = myStorage->entity(*anIter);
- }
myAttributes.push_back(anEntity);
SketchSolver_EntityType aType = anEntity->type();
}
}
}
-
-bool SketchSolver_Constraint::isUsed(FeaturePtr theFeature) const
-{
- const std::list<ConstraintWrapperPtr>& aCList = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aCList.begin();
- for (; aCIt != aCList.end(); ++aCIt)
- if ((*aCIt)->isUsed(theFeature))
- return true;
-
- std::list<AttributePtr> anAttrList =
- theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anAttrIt = anAttrList.begin();
- for (; anAttrIt != anAttrList.end(); ++ anAttrIt)
- if (isUsed(*anAttrIt))
- return true;
-
- return false;
-}
-
-bool SketchSolver_Constraint::isUsed(AttributePtr theAttribute) const
-{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
- else
- anAttribute = aRefAttr->attr();
- }
-
- const std::list<ConstraintWrapperPtr>& aCList = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aCList.begin();
- for (; aCIt != aCList.end(); ++aCIt)
- if ((*aCIt)->isUsed(theAttribute))
- return true;
- return false;
-}
#include "SketchSolver.h"
#include <SketchSolver_Storage.h>
+#include <PlaneGCSSolver_Update.h>
#include <SketchPlugin_Constraint.h>
protected:
/// Default constructor
SketchSolver_Constraint()
- : myGroupID(GID_UNKNOWN),
- myType(CONSTRAINT_UNKNOWN)
+ : myType(CONSTRAINT_UNKNOWN)
{}
public:
/// Constructor based on SketchPlugin constraint
- SKETCHSOLVER_EXPORT SketchSolver_Constraint(ConstraintPtr theConstraint);
+ SketchSolver_Constraint(ConstraintPtr theConstraint);
virtual ~SketchSolver_Constraint() {}
/// \brief Initializes parameters and start constraint creation
- /// \param theStorage [in] storage where to place new constraint
- /// \param theGroupID [in] group for constraint
- /// \param theSketchID [in] sketch for constraint
- void process(StoragePtr theStorage, const GroupID& theGroupID, const EntityID& theSketchID);
+ /// \param theStorage [in] storage where to place new constraint
+ /// \param theEventsBlocked [in] all events from this constraint should be blocked
+ void process(StoragePtr theStorage, bool theEvensBlocked);
+
+ /// \brief Notify this object about the feature is changed somewhere
+ virtual void notify(const FeaturePtr& theFeature, PlaneGCSSolver_Update* theUpdater) {}
/// \brief Update constraint
- SKETCHSOLVER_EXPORT virtual void update();
+ virtual void update();
/// \brief Tries to remove constraint
/// \return \c false, if current constraint contains another SketchPlugin constraints
/// (like for multiple coincidence)
- SKETCHSOLVER_EXPORT virtual bool remove();
+ virtual bool remove();
+
+ /// \brief Block or unblock events from this constraint
+ virtual void blockEvents(bool isBlocked);
/// \brief Obtain a type of SketchPlugin constraint
- SKETCHSOLVER_EXPORT static SketchSolver_ConstraintType TYPE(ConstraintPtr theConstraint);
+ static SketchSolver_ConstraintType TYPE(ConstraintPtr theConstraint);
/// \brief Returns the type of constraint
virtual SketchSolver_ConstraintType getType() const
{ return myType; }
- /// \brief Returns list of attributes of constraint
- const std::list<EntityWrapperPtr>& attributes() const
- { return myAttributes; }
-
- /// \brief Verify the feature or any its attribute is used by constraint
- virtual bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used by constraint
- virtual bool isUsed(AttributePtr theAttribute) const;
-
- /// \brief Notify constraint, that coincidence appears or removed
- virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
- EntityWrapperPtr theCoincAttr2) { /* implement in derived class */ }
-
/// \brief Shows error message
const std::string& error() const
{ return myErrorMsg; }
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes);
/// \brief This method is used in derived objects to check consistency of constraint.
/// E.g. the distance between line and point may be signed.
{ myErrorMsg.clear(); }
protected:
- GroupID myGroupID; ///< identifier of the group, the constraint belongs to
- EntityID mySketchID; ///< identifier of the sketch, the constraint belongs to
ConstraintPtr myBaseConstraint; ///< base SketchPlugin constraint
+ ConstraintWrapperPtr mySolverConstraint; ///< wrapper for PlaneGCS constraint
/// storage, which contains all information about entities and constraints
StoragePtr myStorage;
// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
#include <SketchSolver_ConstraintAngle.h>
-#include <SketchSolver_Manager.h>
-
-#include <GeomAPI_Dir2d.h>
-#include <GeomAPI_Lin2d.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
#include <ModelAPI_AttributeInteger.h>
-
#include <SketchPlugin_ConstraintAngle.h>
-#include <cmath>
-
void SketchSolver_ConstraintAngle::getAttributes(
- double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+ EntityWrapperPtr& theValue, std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
-
- myAngle = theValue;
myType = myBaseConstraint->integer(SketchPlugin_ConstraintAngle::TYPE_ID())->value();
}
void SketchSolver_ConstraintAngle::adjustConstraint()
{
- static const double aTol = 1000. * tolerance;
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
- //if (fabs(myAngle - aConstraint->value()) < aTol)
- // return;
- myAngle = aConstraint->value();
- aBuilder->adjustConstraint(aConstraint);
- myStorage->addConstraint(myBaseConstraint, aConstraint);
-
int aType = myBaseConstraint->integer(SketchPlugin_ConstraintAngle::TYPE_ID())->value();
if (aType != myType) {
myType = aType;
{
public:
/// Constructor based on SketchPlugin constraint
- SketchSolver_ConstraintAngle(ConstraintPtr theConstraint) :
- SketchSolver_Constraint(theConstraint),
- myAngle(0.0)
+ SketchSolver_ConstraintAngle(ConstraintPtr theConstraint)
+ : SketchSolver_Constraint(theConstraint)
{}
/// \brief This method is used in derived objects to check consistence of constraint.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
protected:
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
private:
- double myAngle;
int myType;
};
#include <SketchSolver_ConstraintCoincidence.h>
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+
+void SketchSolver_ConstraintCoincidence::process()
+{
+ cleanErrorMsg();
+ if (!myBaseConstraint || !myStorage) {
+ // Not enough parameters are assigned
+ return;
+ }
+
+ EntityWrapperPtr aValue;
+ std::vector<EntityWrapperPtr> anAttributes;
+ getAttributes(aValue, anAttributes);
+ if (!myErrorMsg.empty())
+ return;
+ if (anAttributes.empty()) {
+ myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
+ return;
+ }
+
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+ mySolverConstraint = aBuilder->createConstraint(
+ myBaseConstraint, getType(),
+ aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
+
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateCoincidence::GROUP());
+ myStorage->notify(myBaseConstraint);
+}
void SketchSolver_ConstraintCoincidence::getAttributes(
- double& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
return;
}
- if (theAttributes[1]) {
+ if (theAttributes[1])
myType = CONSTRAINT_PT_PT_COINCIDENT;
- if (myStorage->isFixed(theAttributes[1]) && !myStorage->isFixed(theAttributes[0])) {
- // fixed point should go first
- EntityWrapperPtr aTemp = theAttributes[0];
- theAttributes[0] = theAttributes[1];
- theAttributes[1] = aTemp;
- }
- // Set the slave (second) point the same as master (first) point.
- // This will allow to skip adding point-point coincidence to the set of constraints
- // and give us speed-up in solving the set of equations
- myStorage->addCoincidentPoints(theAttributes[0], theAttributes[1]);
- }
else if (theAttributes[2]) {
// check the type of entity (line or circle)
SketchSolver_EntityType anEntType = theAttributes[2]->type();
} else
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
}
+
+void SketchSolver_ConstraintCoincidence::notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update* theUpdater)
+{
+ PlaneGCSSolver_UpdateCoincidence* anUpdater =
+ static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
+ bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back());
+ if (isAccepted) {
+ if (!myInSolver) {
+ myInSolver = true;
+ myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
+ }
+ } else {
+ if (myInSolver) {
+ myInSolver = false;
+ myStorage->removeConstraint(myBaseConstraint);
+ }
+ }
+}
{
public:
/// Constructor based on SketchPlugin constraint
- SKETCHSOLVER_EXPORT SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
- SketchSolver_Constraint(theConstraint)
+ SketchSolver_ConstraintCoincidence(ConstraintPtr theConstraint) :
+ SketchSolver_Constraint(theConstraint),
+ myInSolver(false)
{}
+ /// \brief Notify this object about the feature is changed somewhere
+ virtual void notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update* theUpdater) override;
+
protected:
+ /// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
+ virtual void process() override;
+
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
+
+protected:
+ bool myInSolver; ///< shows the constraint is added to the solver
};
#endif
{
}
-void SketchSolver_ConstraintCollinear::notifyCoincidenceChanged(
- EntityWrapperPtr theCoincAttr1,
- EntityWrapperPtr theCoincAttr2)
-{
- bool used = true;
-
- // obtain IDs of all boundary points of lines
- EntityID aPointIDs[4];
- for (int i = 0; i < 2; ++i) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)));
- if (!aRefAttr->object())
- continue;
- FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
- AttributePtr aLinePt = aLine->attribute(SketchPlugin_Line::START_ID());
- aPointIDs[2*i] = myStorage->entity(aLinePt)->id();
- aLinePt = aLine->attribute(SketchPlugin_Line::END_ID());
- aPointIDs[2*i + 1] = myStorage->entity(aLinePt)->id();
- }
-
- EntityWrapperPtr anAttrs[2] = {theCoincAttr1, theCoincAttr2};
- for (int i = 0; i < 2 && used; ++i) {
- if (anAttrs[i]->baseAttribute())
- used = used && isUsed(anAttrs[i]->baseAttribute());
- else
- used = used && isUsed(anAttrs[i]->baseFeature());
-
- if (!used) {
- if (anAttrs[i]->type() == ENTITY_POINT) {
- EntityID anID = anAttrs[i]->id();
- for (int j = 0; j < 4; ++j)
- if (anID == aPointIDs[j]) {
- used = true;
- break;
- }
- }
- }
- }
-
- if (used) {
- remove();
- process();
- }
-}
+////void SketchSolver_ConstraintCollinear::notifyCoincidenceChanged(
+//// EntityWrapperPtr theCoincAttr1,
+//// EntityWrapperPtr theCoincAttr2)
+////{
+//// bool used = true;
+////
+//// // obtain IDs of all boundary points of lines
+//// EntityID aPointIDs[4];
+//// for (int i = 0; i < 2; ++i) {
+//// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+//// myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)));
+//// if (!aRefAttr->object())
+//// continue;
+//// FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
+//// AttributePtr aLinePt = aLine->attribute(SketchPlugin_Line::START_ID());
+//// aPointIDs[2*i] = myStorage->entity(aLinePt)->id();
+//// aLinePt = aLine->attribute(SketchPlugin_Line::END_ID());
+//// aPointIDs[2*i + 1] = myStorage->entity(aLinePt)->id();
+//// }
+////
+//// EntityWrapperPtr anAttrs[2] = {theCoincAttr1, theCoincAttr2};
+//// for (int i = 0; i < 2 && used; ++i) {
+//// if (anAttrs[i]->baseAttribute())
+//// used = used && isUsed(anAttrs[i]->baseAttribute());
+//// else
+//// used = used && isUsed(anAttrs[i]->baseFeature());
+////
+//// if (!used) {
+//// if (anAttrs[i]->type() == ENTITY_POINT) {
+//// EntityID anID = anAttrs[i]->id();
+//// for (int j = 0; j < 4; ++j)
+//// if (anID == aPointIDs[j]) {
+//// used = true;
+//// break;
+//// }
+//// }
+//// }
+//// }
+////
+//// if (used) {
+//// remove();
+//// process();
+//// }
+////}
{
public:
/// Constructor based on SketchPlugin constraint
- SKETCHSOLVER_EXPORT SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint);
+ SketchSolver_ConstraintCollinear(ConstraintPtr theConstraint);
virtual ~SketchSolver_ConstraintCollinear() {}
- /// \brief Notify constraint, that coincidence appears or removed
- virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
- EntityWrapperPtr theCoincAttr2);
+//// /// \brief Notify constraint, that coincidence appears or removed
+//// virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
+//// EntityWrapperPtr theCoincAttr2);
};
#endif
void SketchSolver_ConstraintDistance::getAttributes(
- double& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
void SketchSolver_ConstraintDistance::adjustConstraint()
{
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
+ ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint);
// Adjust point-point distance if the points are equal
if (getType() == CONSTRAINT_PT_PT_DISTANCE) {
- const std::list<EntityWrapperPtr>& aSubs = aConstraint->entities();
- if (aSubs.front()->isEqual(aSubs.back())) {
- // Change X coordinate of second point to eliminate coincidence
- ParameterWrapperPtr aX = aSubs.back()->parameters().front();
- aX->setValue(aX->value() + 1.0);
- myStorage->update(aX);
- }
+//// AttributePtr aPt1 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
+//// AttributePtr aPt2 = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B());
+////
+//// BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+//// std::shared_ptr<GeomAPI_Pnt2d> aPoint1 = aBuilder->point(myStorage->entity(aPt1));
+//// EntityWrapperPtr anEntity2 = myStorage->entity(aPt2);
+//// std::shared_ptr<GeomAPI_Pnt2d> aPoint2 = aBuilder->point(anEntity2);
+////
+//////// if (aPoint1->distance(aPoint2) < tolerance) {
+//////// // Change X coordinate of second point to eliminate coincidence
+//////// ParameterWrapperPtr aX = aSubs.back()->parameters().front();
+//////// aX->setValue(aX->value() + 1.0);
+//////// myStorage->update(aX);
+//////// }
return;
}
// Adjust point-line distance
if (fabs(myPrevValue) == fabs(aConstraint->value())) {
// sign of distance is not changed
- aConstraint->setValue(myPrevValue);
- myStorage->addConstraint(myBaseConstraint, aConstraint);
+//// aConstraint->setValue(myPrevValue);
+//// myStorage->addConstraint(myBaseConstraint, aConstraint);
return;
}
- // Adjust the sign of constraint value
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- aBuilder->adjustConstraint(aConstraint);
- myStorage->addConstraint(myBaseConstraint, aConstraint);
+//// // Adjust the sign of constraint value
+//// BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+////
+//// std::shared_ptr<GeomAPI_Lin2d> aLine;
+//// std::shared_ptr<GeomAPI_Pnt2d> aPoint;
+//// for (int i = 0; i < 2; ++i) {
+//// AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i));
+//// EntityWrapperPtr anEntity = myStorage->entity(anAttr);
+//// if (anEntity->type() == ENTITY_POINT)
+//// aPoint = aBuilder->point(anEntity);
+//// else if (anEntity->type() == ENTITY_LINE)
+//// aLine = aBuilder->line(anEntity);
+//// }
+////
+//// std::shared_ptr<GeomAPI_XY> aLineVec = aLine->direction()->xy();
+//// std::shared_ptr<GeomAPI_XY> aPtLineVec = aPoint->xy()->decreased(aLine->location()->xy());
+//// if (aLineVec->cross(aPtLineVec) * aConstraint->value() < 0.0)
+//// aConstraint->setValue(aConstraint->value() * (-1.0));
}
void SketchSolver_ConstraintDistance::update()
{
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
+ ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint);
myPrevValue = aConstraint->value();
SketchSolver_Constraint::update();
{}
/// \brief Update constraint
- virtual void update();
+ virtual void update() override;
protected:
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
/// \brief This method is used in derived objects to check consistence of constraint.
/// E.g. the distance between line and point may be signed.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
private:
double myPrevValue; ///< previous value of distance (for correct calculation of a distance sign)
#include <SketchSolver_ConstraintEqual.h>
#include <SketchSolver_Error.h>
+#include <ModelAPI_AttributeRefAttr.h>
+#include <SketchPlugin_Line.h>
+
void SketchSolver_ConstraintEqual::getAttributes(
- double& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
break;
default:
myType = CONSTRAINT_EQUAL_LINES;
+
+ AttributeRefAttrPtr aRefLine1 =
+ myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ FeaturePtr aLine1 = ModelAPI_Feature::feature(aRefLine1->object());
+ if (aLine1) {
+ // store length of first line as a value for constraint
+ // (will be used to make equal lengths of lines)
+ theValue = myStorage->entity(aLine1->attribute(SketchPlugin_Line::LENGTH_ID()));
+ }
break;
}
}
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
};
#endif
#include <SketchSolver_ConstraintFixed.h>
#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
+#include <PlaneGCSSolver_ConstraintWrapper.h>
+#include <PlaneGCSSolver_EntityWrapper.h>
+#include <PlaneGCSSolver_PointWrapper.h>
-#include <GeomAPI_Pnt2d.h>
-#include <GeomAPI_XY.h>
-#include <GeomDataAPI_Point2D.h>
-#include <ModelAPI_AttributeDouble.h>
-
-#include <math.h>
SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(ConstraintPtr theConstraint)
- : SketchSolver_Constraint()
+ : SketchSolver_Constraint(theConstraint)
{
- myBaseConstraint = theConstraint;
myType = CONSTRAINT_FIXED;
- AttributeRefAttrPtr anAttribute =
- theConstraint->refattr(SketchPlugin_ConstraintRigid::ENTITY_A());
- if (anAttribute->isObject())
- myFixedFeature = ModelAPI_Feature::feature(anAttribute->object());
- else
- myFixedAttribute = anAttribute->attr();
+//// AttributeRefAttrPtr anAttribute =
+//// theConstraint->refattr(SketchPlugin_ConstraintRigid::ENTITY_A());
+//// if (anAttribute->isObject())
+//// myFixedFeature = ModelAPI_Feature::feature(anAttribute->object());
+//// else
+//// myFixedAttribute = anAttribute->attr();
}
SketchSolver_ConstraintFixed::SketchSolver_ConstraintFixed(FeaturePtr theFeature)
myBaseFeature(theFeature)
{
myType = CONSTRAINT_FIXED;
- process();
+//// process();
+}
+
+void SketchSolver_ConstraintFixed::blockEvents(bool isBlocked)
+{
+ if (myBaseFeature)
+ myBaseFeature->data()->blockSendAttributeUpdated(isBlocked);
+ if (myBaseConstraint)
+ SketchSolver_Constraint::blockEvents(isBlocked);
}
void SketchSolver_ConstraintFixed::process()
{
cleanErrorMsg();
- if ((!myBaseConstraint && !myBaseFeature) || !myStorage || myGroupID == GID_UNKNOWN) {
+ if ((!myBaseConstraint && !myBaseFeature) || !myStorage) {
// Not enough parameters are assigned
return;
}
- ParameterWrapperPtr aValue;
+ EntityWrapperPtr aValue;
std::vector<EntityWrapperPtr> anEntities;
getAttributes(aValue, anEntities);
- if (!myErrorMsg.empty() || anEntities.empty())
+ if (anEntities.empty())
+ myErrorMsg = SketchSolver_Error::ALREADY_FIXED();
+ if (!myErrorMsg.empty())
return;
fixFeature(anEntities.front());
}
void SketchSolver_ConstraintFixed::fixFeature(EntityWrapperPtr theFeature)
{
- // extract feature from the group
- if (theFeature->baseAttribute())
- myStorage->update(theFeature->baseAttribute(), GID_OUTOFGROUP);
- else if (theFeature->baseFeature())
- myStorage->update(theFeature->baseFeature(), GID_OUTOFGROUP);
+ std::shared_ptr<PlaneGCSSolver_EntityWrapper> anEntity =
+ std::dynamic_pointer_cast<PlaneGCSSolver_EntityWrapper>(theFeature);
+
+ GCS::VEC_pD aParameters; // parameters of entity to be fixed
+
+ // Collect parameters for each type of entity
+ switch (theFeature->type()) {
+ case ENTITY_POINT: {
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aPoint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theFeature);
+ aParameters.push_back(aPoint->point()->x);
+ aParameters.push_back(aPoint->point()->y);
+ break;
+ }
+ case ENTITY_LINE: {
+ std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(anEntity->entity());
+ aParameters.push_back(aLine->p1.x);
+ aParameters.push_back(aLine->p1.y);
+ aParameters.push_back(aLine->p2.x);
+ aParameters.push_back(aLine->p2.y);
+ break;
+ }
+ case ENTITY_CIRCLE: {
+ std::shared_ptr<GCS::Circle> aCircle =
+ std::dynamic_pointer_cast<GCS::Circle>(anEntity->entity());
+ aParameters.push_back(aCircle->center.x);
+ aParameters.push_back(aCircle->center.y);
+ aParameters.push_back(aCircle->rad);
+ break;
+ }
+ case ENTITY_ARC: {
+ myFixedValues.reserve(4);
+ std::shared_ptr<GCS::Arc> anArc = std::dynamic_pointer_cast<GCS::Arc>(anEntity->entity());
+ aParameters.push_back(anArc->center.x);
+ aParameters.push_back(anArc->center.y);
+ aParameters.push_back(anArc->rad);
+ aParameters.push_back(anArc->startAngle);
+ aParameters.push_back(anArc->endAngle);
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Fix given list of parameters
+ std::list<GCSConstraintPtr> aConstraints;
+ myFixedValues.reserve(aParameters.size());
+ GCS::VEC_pD::const_iterator anIt = aParameters.begin();
+ for (int i = 0; anIt != aParameters.end(); ++anIt, ++i) {
+ myFixedValues.push_back(**anIt);
+ aConstraints.push_back(
+ GCSConstraintPtr(new GCS::ConstraintEqual(*anIt, &myFixedValues[i])));
+ }
+
+ myConstraint = ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aConstraints, getType()));
if (myBaseConstraint)
- myStorage->addConstraint(myBaseConstraint, std::list<ConstraintWrapperPtr>());
+ myStorage->addConstraint(myBaseConstraint, myConstraint);
+ else
+ myStorage->addTemporaryConstraint(myConstraint);
}
void SketchSolver_ConstraintFixed::getAttributes(
- ParameterWrapperPtr& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- EntityWrapperPtr aSolverEntity;
if (myBaseFeature) {
// The feature is fixed.
- myStorage->update(myBaseFeature/*, myGroupID*/);
- aSolverEntity = myStorage->entity(myBaseFeature);
+ myStorage->update(myBaseFeature);
+ EntityWrapperPtr aSolverEntity = myStorage->entity(myBaseFeature);
+ if (aSolverEntity)
+ theAttributes.push_back(aSolverEntity);
} else if (myBaseConstraint) {
// Constraint Fixed is added by user.
// Get the attribute of constraint (it should be alone in the list of constraints).
- AttributePtr anAttr = myBaseConstraint->attribute(SketchPlugin_ConstraintRigid::ENTITY_A());
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttr);
- if (!aRefAttr || !aRefAttr->isInitialized()) {
- myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
- return;
- }
-
- myStorage->update(anAttr, myGroupID);
- aSolverEntity = myStorage->entity(anAttr);
+ std::vector<EntityWrapperPtr> anAttributes;
+ SketchSolver_Constraint::getAttributes(theValue, anAttributes);
+ std::vector<EntityWrapperPtr>::const_iterator anIt = anAttributes.begin();
+ for (; anIt != anAttributes.end(); ++anIt)
+ if (*anIt)
+ theAttributes.push_back(*anIt);
} else
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
-
- if (aSolverEntity)
- theAttributes.push_back(aSolverEntity);
-}
-
-
-bool SketchSolver_ConstraintFixed::remove()
-{
- cleanErrorMsg();
- // Move fixed entities back to the current group
- FeaturePtr aFeature = myBaseFeature;
- if (myBaseConstraint) {
- if (myFixedFeature)
- aFeature = myFixedFeature;
- else if (myFixedAttribute)
- myStorage->update(AttributePtr(myFixedAttribute), myGroupID);
- }
- if (aFeature)
- myStorage->update(aFeature, myGroupID);
- myStorage->setNeedToResolve(true);
-
- // Remove constraint or base feature
- if (myBaseConstraint) {
- bool isRemoved = false;
- if (aFeature)
- isRemoved = myStorage->removeEntity(aFeature);
- return SketchSolver_Constraint::remove() || isRemoved;
- } else if (myBaseFeature)
- myStorage->removeEntity(myBaseFeature);
- return true;
}
*
* Fixed constraint may have NULL basic SketchPlugin constraint,
* because the Fixed constraint may be temporary for correct moving of objects.
- *
- * Fixed constraint does not create a constraint, but builds the entities in separate group,
- * so they will not be moved while resolving the set of constraints.
*/
class SketchSolver_ConstraintFixed : public SketchSolver_Constraint
{
public:
/// Creates constraint to manage the given constraint from plugin
SketchSolver_ConstraintFixed(ConstraintPtr theConstraint);
- /// Creates temporary constraint based on feature
+ /// Creates temporary constraint based on feature (useful while the feature is being moved)
SketchSolver_ConstraintFixed(FeaturePtr theFeature);
- /// \brief Tries to remove constraint
- /// \return \c false, if current constraint contains another
- /// SketchPlugin constraints (like for multiple coincidence)
- virtual bool remove();
+ /// \brief Block or unblock events from this constraint
+ virtual void blockEvents(bool isBlocked) override;
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
- virtual void process();
+ virtual void process() override;
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(ParameterWrapperPtr& theValue,
- std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
/// \brief Fixed feature basing on its type
/// \param theFeature [in] feature, converted to solver specific format
virtual void fixFeature(EntityWrapperPtr theFeature);
-protected:
+private:
FeaturePtr myBaseFeature; ///< fixed feature (when it is set, myBaseConstraint should be NULL)
-private:
- AttributePtr myFixedAttribute; ///< possible attribute of a fixed constraint (for correct remove)
- FeaturePtr myFixedFeature; ///< possible attribute of a fixed constraint (for correct remove)
+ ConstraintWrapperPtr myConstraint;
+ std::vector<double> myFixedValues;
};
#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-#include <SketchSolver_ConstraintFixedArcRadius.h>
-#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-
-#include <SketchPlugin_Arc.h>
-#include <GeomAPI_Pnt2d.h>
-
-SketchSolver_ConstraintFixedArcRadius::SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature)
- : SketchSolver_ConstraintFixed(theFeature)
-{
- myType = CONSTRAINT_RADIUS;
- process();
-}
-
-void SketchSolver_ConstraintFixedArcRadius::process()
-{
- cleanErrorMsg();
- if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
- // Not enough parameters are assigned
- return;
- }
-
- if (myBaseFeature->getKind() != SketchPlugin_Arc::ID()) {
- myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
- return;
- }
-
- ParameterWrapperPtr aValue;
- std::vector<EntityWrapperPtr> anEntities;
- getAttributes(aValue, anEntities);
- if (!myErrorMsg.empty() || anEntities.empty())
- return;
- fixFeature(anEntities.front());
-}
-
-void SketchSolver_ConstraintFixedArcRadius::fixFeature(EntityWrapperPtr theFeature)
-{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- // Calculate radius of the arc
- std::list<EntityWrapperPtr> aSubs = theFeature->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
- std::shared_ptr<GeomAPI_Pnt2d> aCenter = aBuilder->point(*aSubIt++);
- std::shared_ptr<GeomAPI_Pnt2d> aStart = aBuilder->point(*aSubIt++);
- double aRadius = aCenter->distance(aStart);
-
- // Create constraint
- std::list<ConstraintWrapperPtr> aConstrList = aBuilder->createConstraint(ConstraintPtr(),
- myGroupID, mySketchID, myType, aRadius, EntityWrapperPtr(), EntityWrapperPtr(), theFeature);
- myRadiusConstraint = aConstrList.front();
- myStorage->addConstraint(ConstraintPtr(), myRadiusConstraint);
-}
-
-bool SketchSolver_ConstraintFixedArcRadius::remove()
-{
- bool isFullyRemoved = true;
- if (myBaseFeature)
- isFullyRemoved = myStorage->removeEntity(myBaseFeature) && isFullyRemoved;
- if (myRadiusConstraint)
- isFullyRemoved = myStorage->removeConstraint(ConstraintPtr()) &&
- myStorage->remove(myRadiusConstraint) && isFullyRemoved;
- return isFullyRemoved;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_ConstraintFixedArcRadiusArcRadius.h
-// Created: 22 Jan 2016
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_ConstraintFixedArcRadius_H_
-#define SketchSolver_ConstraintFixedArcRadius_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_ConstraintFixed.h>
-
-/** \class SketchSolver_ConstraintFixedArcRadius
- * \ingroup Plugins
- * \brief Fix radius of the arc. Temporary constraint. Based on an arc, sharp!
- */
-class SketchSolver_ConstraintFixedArcRadius : public SketchSolver_ConstraintFixed
-{
-public:
- /// Creates temporary constraint based on feature
- SketchSolver_ConstraintFixedArcRadius(FeaturePtr theFeature);
-
- /// \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();
-
- /// \brief Fix radius of arc
- /// \param theFeature [in] feature, converted to solver specific format
- virtual void fixFeature(EntityWrapperPtr theFeature);
-
-private:
- ConstraintWrapperPtr myRadiusConstraint;
-};
-
-#endif
#include <SketchSolver_ConstraintLength.h>
#include <SketchSolver_Error.h>
+#include <SketchPlugin_Line.h>
+
void SketchSolver_ConstraintLength::getAttributes(
- double& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
return;
}
- // Get boundary points of line segment and create point-point distance constraint
- std::list<EntityWrapperPtr> aSubs = theAttributes[2]->subEntities();
- theAttributes.assign(theAttributes.size(), EntityWrapperPtr());
- std::vector<EntityWrapperPtr>::iterator anAttrIt = theAttributes.begin();
- std::list<EntityWrapperPtr>::const_iterator aSubIt = aSubs.begin();
- for (; aSubIt != aSubs.end(); ++aSubIt, ++anAttrIt)
- *anAttrIt = *aSubIt;
+ AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ FeaturePtr aLine = ModelAPI_Feature::feature(aRefAttr->object());
+
+ theAttributes[0] = myStorage->entity(aLine->attribute(SketchPlugin_Line::START_ID()));
+ theAttributes[1] = myStorage->entity(aLine->attribute(SketchPlugin_Line::END_ID()));
myType = CONSTRAINT_PT_PT_DISTANCE;
}
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
};
#endif
// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
#include <SketchSolver_ConstraintMiddle.h>
+#include <PlaneGCSSolver_ConstraintWrapper.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
-#include <SketchSolver_Builder.h>
-#include <SketchSolver_Manager.h>
-
-#include <GeomAPI_XY.h>
-
-SketchSolver_ConstraintMiddle::SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint)
- : SketchSolver_Constraint(theConstraint)
+void SketchSolver_ConstraintMiddle::getAttributes(
+ EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes)
{
+ SketchSolver_Constraint::getAttributes(theValue, theAttributes);
}
-void SketchSolver_ConstraintMiddle::notifyCoincidenceChanged(
- EntityWrapperPtr theCoincAttr1,
- EntityWrapperPtr theCoincAttr2)
+void SketchSolver_ConstraintMiddle::notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update* theUpdater)
{
- // Check the coincidence between point and line has been changed
- AttributePtr aPoint;
- FeaturePtr aLine;
- EntityWrapperPtr anEntities[2] = {theCoincAttr1, theCoincAttr2};
- for (int i = 0; i < 2; ++i) {
- if (anEntities[i]->type() == ENTITY_POINT)
- aPoint = anEntities[i]->baseAttribute();
- else if (anEntities[i]->type() == ENTITY_LINE)
- aLine = anEntities[i]->baseFeature();
- }
- if (!aPoint || !aLine)
- return;
-
- // Check the attributes of middle-point constraint are the same point and line
- bool isSameAttr = true;
- for (int i = 0; i < 2 && isSameAttr; ++i) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ATTRIBUTE(i)));
- if (!aRefAttr)
- {
- // It seems the Middle point constraint has been deleted, so keep it unchanged.
- // It will be removed later.
- return;
+ PlaneGCSSolver_UpdateCoincidence* anUpdater =
+ static_cast<PlaneGCSSolver_UpdateCoincidence*>(theUpdater);
+ bool isAccepted = anUpdater->checkCoincidence(myAttributes.front(), myAttributes.back());
+ if (isAccepted) {
+ if (!myInSolver) {
+ myInSolver = true;
+
+ if (myMiddle) {
+ // remove previously adde constraint
+ myStorage->removeConstraint(myBaseConstraint);
+ // merge divided constraints into single object
+ std::list<GCSConstraintPtr> aGCSConstraints;
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(myMiddle);
+ aGCSConstraints.push_back(aConstraint->constraints().front());
+ aConstraint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(mySolverConstraint);
+ aGCSConstraints.push_back(aConstraint->constraints().front());
+
+ myMiddle = ConstraintWrapperPtr();
+ mySolverConstraint = ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints, CONSTRAINT_MIDDLE_POINT));
+ }
+
+ myStorage->addConstraint(myBaseConstraint, mySolverConstraint);
}
- if (aRefAttr->isObject()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
- isSameAttr = (aFeature == aLine);
- } else
- isSameAttr = (aRefAttr->attr() == aPoint);
- }
+ } else {
+ if (myInSolver) {
+ myInSolver = false;
+ myStorage->removeConstraint(myBaseConstraint);
+ }
+
+ if (!myMiddle) {
+ // divide solver constraints to the middle point and point-line coincidence
+ std::shared_ptr<PlaneGCSSolver_ConstraintWrapper> aConstraint =
+ std::dynamic_pointer_cast<PlaneGCSSolver_ConstraintWrapper>(mySolverConstraint);
+ std::list<GCSConstraintPtr> aGCSConstraints = aConstraint->constraints();
- if (isSameAttr) {
- remove();
- process();
+ myMiddle = ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.front(), CONSTRAINT_MIDDLE_POINT));
+ mySolverConstraint = ConstraintWrapperPtr(
+ new PlaneGCSSolver_ConstraintWrapper(aGCSConstraints.back(), CONSTRAINT_MIDDLE_POINT));
+
+ // send middle constraint only
+ myStorage->addConstraint(myBaseConstraint, myMiddle);
+ }
}
}
#ifndef SketchSolver_ConstraintMiddle_H_
#define SketchSolver_ConstraintMiddle_H_
-#include <SketchSolver_Constraint.h>
+#include <SketchSolver_ConstraintCoincidence.h>
/** \class SketchSolver_ConstraintMiddle
* \ingroup Plugins
* \brief Converts middle-point constraint to the constraint applicable for solver
*/
-class SketchSolver_ConstraintMiddle : public SketchSolver_Constraint
+class SketchSolver_ConstraintMiddle : public SketchSolver_ConstraintCoincidence
{
public:
/// Constructor based on SketchPlugin constraint
- SKETCHSOLVER_EXPORT SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint);
+ SketchSolver_ConstraintMiddle(ConstraintPtr theConstraint)
+ : SketchSolver_ConstraintCoincidence(theConstraint)
+ {}
- virtual ~SketchSolver_ConstraintMiddle() {}
+ /// \brief Notify this object about the feature is changed somewhere
+ virtual void notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update* theUpdater) override;
- /// \brief Notify constraint, that coincidence appears or removed
- virtual void notifyCoincidenceChanged(EntityWrapperPtr theCoincAttr1,
- EntityWrapperPtr theCoincAttr2);
+protected:
+ /// \brief Generate list of attributes of constraint in order useful for constraints
+ /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
+ /// \param[out] theAttributes list of attributes to be filled
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
+
+private:
+ ConstraintWrapperPtr myMiddle;
};
#endif
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
+
+#include <GeomAPI_XY.h>
+#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeRefList.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_Circle.h>
+
+
+static void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const AttributePoint2DPtr& theOriginal,
+ const AttributePoint2DPtr& theMirrored);
+
+static void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const FeaturePtr& theOriginal,
+ const FeaturePtr& theMirrored);
+
+
void SketchSolver_ConstraintMirror::getAttributes(
- EntityWrapperPtr& theMirrorLine,
- std::vector<EntityWrapperPtr>& theBaseEntities,
- std::vector<EntityWrapperPtr>& theMirrorEntities)
+ EntityWrapperPtr&,
+ std::vector<EntityWrapperPtr>&)
{
- AttributePtr aMirLineAttr = myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_A());
AttributeRefAttrPtr aMirLineRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(aMirLineAttr);
+ myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
if (!aMirLineRefAttr || !aMirLineRefAttr->isInitialized() || !aMirLineRefAttr->isObject()) {
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return;
}
+ FeaturePtr aMirrorLine = ModelAPI_Feature::feature(aMirLineRefAttr->object());
+ myFeatures.insert(aMirrorLine);
+
myType = TYPE(myBaseConstraint);
- myStorage->update(aMirLineAttr/*, myGroupID*/);
- theMirrorLine = myStorage->entity(aMirLineAttr);
-
- // Create SolveSpace entity for all features
- AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
- AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_C()));
+ myStorage->update(aMirrorLine);
+
+
+ AttributeRefListPtr aBaseRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
+ AttributeRefListPtr aMirroredRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
myNumberOfObjects = aMirroredRefList->size();
if (!aBaseRefList || !aMirroredRefList) {
myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
return;
}
- std::list<ObjectPtr> aBaseList = aBaseRefList->list();
- std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
-
- FeaturePtr aFeature;
- for (int i = 0; i < 2; i++) {
- std::list<ObjectPtr>::iterator anIter = i == 0 ? aBaseList.begin() : aMirroredList.begin();
- std::list<ObjectPtr>::iterator aEndIter = i == 0 ? aBaseList.end() : aMirroredList.end();
- std::vector<EntityWrapperPtr>* aList = i == 0 ? &theBaseEntities : & theMirrorEntities;
- for ( ; anIter != aEndIter; anIter++) {
- aFeature = ModelAPI_Feature::feature(*anIter);
- if (!aFeature)
- continue;
-
- myStorage->update(aFeature, GID_UNKNOWN, true);
- aList->push_back(myStorage->entity(aFeature));
+ // store only original entities because mirrored ones
+ // will be updated separately in adjustConstraint
+ std::list<ObjectPtr> aList = aBaseRefList->list();
+ std::list<ObjectPtr>::iterator anIt = aList.begin();
+ for (; anIt != aList.end(); ++anIt) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+ if (aFeature) {
+ myStorage->update(aFeature);
+ myFeatures.insert(aFeature);
}
}
-
- if (theBaseEntities.size() > theMirrorEntities.size() || aMirroredList.empty())
- myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
+ // add mirrored features to the list
+ aList = aMirroredRefList->list();
+ for (anIt = aList.begin(); anIt != aList.end(); ++anIt) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+ if (aFeature)
+ myFeatures.insert(aFeature);
+ }
}
void SketchSolver_ConstraintMirror::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
+ if (!myBaseConstraint || !myStorage) {
// Not enough parameters are assigned
return;
}
EntityWrapperPtr aMirrorLine;
std::vector<EntityWrapperPtr> aBaseList;
- std::vector<EntityWrapperPtr> aMirrorList;
- getAttributes(aMirrorLine, aBaseList, aMirrorList);
+ getAttributes(aMirrorLine, aBaseList);
if (!myErrorMsg.empty())
return;
- if (aBaseList.size() != aMirrorList.size()) {
- myErrorMsg = SketchSolver_Error::INCORRECT_MIRROR_ATTRIBUTE();
- return;
- }
-
- std::list<ConstraintWrapperPtr> aNewConstraints;
- SketchSolver_ConstraintType aConstrType = getType();
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aMirConstrList;
-
- // update mirrored features to be in the current group
- std::vector<EntityWrapperPtr>::iterator aMIt = aMirrorList.begin();
- for (; aMIt != aMirrorList.end(); ++aMIt)
- myStorage->update((*aMIt)->baseFeature(), myGroupID);
-
- std::vector<EntityWrapperPtr>::iterator aBIt = aBaseList.begin();
- for (aMIt = aMirrorList.begin(); aBIt != aBaseList.end(); ++aBIt, ++aMIt) {
- aNewConstraints = aBuilder->createConstraint(
- myBaseConstraint, myGroupID, mySketchID, aConstrType,
- 0.0, *aBIt, *aMIt, aMirrorLine);
- aMirConstrList.insert(aMirConstrList.end(), aNewConstraints.begin(), aNewConstraints.end());
- }
- myStorage->addConstraint(myBaseConstraint, aMirConstrList);
-
adjustConstraint();
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
}
{
BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
- for (; aCIt != aConstraints.end(); ++aCIt)
- if ((*aCIt)->type() == CONSTRAINT_SYMMETRIC)
- aBuilder->adjustConstraint(*aCIt);
+ AttributeRefAttrPtr aMirrLineRefAttr =
+ myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ std::shared_ptr<GeomAPI_Lin2d> aMirrorLine =
+ aBuilder->line(ModelAPI_Feature::feature(aMirrLineRefAttr->object()));
+
+ AttributeRefListPtr aBaseRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
+ AttributeRefListPtr aMirroredRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
+
+ std::list<ObjectPtr> aBaseList = aBaseRefList->list();
+ std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
+ std::list<ObjectPtr>::iterator aBIt, aMIt;
+ for (aBIt = aBaseList.begin(), aMIt = aMirroredList.begin();
+ aBIt != aBaseList.end() && aMIt != aMirroredList.end();
+ ++aBIt, ++aMIt) {
+ FeaturePtr aBase = ModelAPI_Feature::feature(*aBIt);
+ FeaturePtr aMirrored = ModelAPI_Feature::feature(*aMIt);
+ mirrorEntities(aMirrorLine, aBase, aMirrored);
+ }
+}
+
+void SketchSolver_ConstraintMirror::notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update*)
+{
+ if (myFeatures.find(theFeature) == myFeatures.end())
+ return; // the feature is not used by constraint => nothing to update
+ adjustConstraint();
+}
+
+void SketchSolver_ConstraintMirror::blockEvents(bool isBlocked)
+{
+ std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
+ for (; anIt != myFeatures.end(); ++anIt)
+ (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
+
+ SketchSolver_Constraint::blockEvents(isBlocked);
+}
+
+
+
+
+// ================= Auxiliary functions ==================================
+void mirrorPoints(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const AttributePoint2DPtr& theOriginal,
+ const AttributePoint2DPtr& theMirrored)
+{
+ std::shared_ptr<GeomAPI_Pnt2d> anOriginal = theOriginal->pnt();
+ std::shared_ptr<GeomAPI_Pnt2d> aPtOnLine = theMirrorLine->project(anOriginal);
+ std::shared_ptr<GeomAPI_XY> aPerp = aPtOnLine->xy()->decreased(anOriginal->xy());
+ theMirrored->setValue(anOriginal->x() + aPerp->x() * 2.0, anOriginal->y() + aPerp->y() * 2.0);
+}
+
+void mirrorEntities(const std::shared_ptr<GeomAPI_Lin2d>& theMirrorLine,
+ const FeaturePtr& theOriginal,
+ const FeaturePtr& theMirrored)
+{
+ std::list<AttributePtr> aPoints0 =
+ theOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr> aPoints1 =
+ theMirrored->data()->attributes(GeomDataAPI_Point2D::typeId());
+
+ // process specific features
+ if (theOriginal->getKind() == SketchPlugin_Arc::ID()) {
+ // orientation of arc
+ theMirrored->boolean(SketchPlugin_Arc::INVERSED_ID())->setValue(
+ !theOriginal->boolean(SketchPlugin_Arc::INVERSED_ID())->value());
+ } else if (theOriginal->getKind() == SketchPlugin_Circle::ID()) {
+ // radius of the circle
+ theMirrored->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
+ theOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
+ }
+
+ // mirror all initialized points of features
+ std::list<AttributePtr>::iterator anIt0, anIt1;
+ for (anIt0 = aPoints0.begin(), anIt1 = aPoints1.begin();
+ anIt0 != aPoints0.end() && anIt1 != aPoints1.end(); ++anIt0, ++anIt1) {
+ AttributePoint2DPtr aPt0 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt0);
+ AttributePoint2DPtr aPt1 = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*anIt1);
+ if (aPt0->isInitialized() && aPt1->isInitialized())
+ mirrorPoints(theMirrorLine, aPt0, aPt1);
+ }
}
{}
/// \brief Update constraint
- virtual void update();
+ virtual void update() override;
+
+ /// \brief Notify this object about the feature is changed somewhere
+ virtual void notify(const FeaturePtr& theFeature, PlaneGCSSolver_Update*) override;
+
+ /// \brief Block or unblock events from this constraint
+ virtual void blockEvents(bool isBlocked) override;
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
- virtual void process();
-
- /// \brief Generate list of attributes of constraint in order useful for constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
- { /* do nothing here */ }
+ virtual void process() override;
/// \brief Generate list of entities of mirror constraint
- /// \param[out] theMirrorLine entity corresponding to mirror line
- /// \param[out] theBaseEntities list of entities to mirror
- /// \param[out] theMirrorEntities list of mirrored entities
- void getAttributes(EntityWrapperPtr& theMirrorLine,
- std::vector<EntityWrapperPtr>& theBaseEntities,
- std::vector<EntityWrapperPtr>& theMirrorEntities);
+ virtual void getAttributes(EntityWrapperPtr&, std::vector<EntityWrapperPtr>&) override;
/// \brief This method is used in derived objects to check consistence of constraint.
/// E.g. the distance between line and point may be signed.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
private:
size_t myNumberOfObjects; ///< number of previously mirrored objects
+ std::set<FeaturePtr> myFeatures; ///< mirror line, original and mirrored features
};
#endif
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-#include <SketchSolver_ConstraintMovement.h>
-#include <SketchSolver_Error.h>
-#include <SketchSolver_Manager.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
-
-#include <GeomDataAPI_Point2D.h>
-
-
-void SketchSolver_ConstraintMovement::process()
-{
- cleanErrorMsg();
- if (!myBaseFeature || !myStorage || myGroupID == GID_UNKNOWN) {
- // Not enough parameters are initialized
- return;
- }
-
- ParameterWrapperPtr aValue;
- getAttributes(aValue, myMovedEntities);
- if (!myErrorMsg.empty() || myMovedEntities.empty()) {
- // Nothing to move, clear the feature to avoid changing its group
- // after removing the Movement constraint.
- myBaseFeature = FeaturePtr();
- return;
- }
-
- std::vector<EntityWrapperPtr>::iterator anEntIt = myMovedEntities.begin();
- for (; anEntIt != myMovedEntities.end(); ++anEntIt)
- fixFeature(*anEntIt);
-}
-
-
-static std::list<EntityWrapperPtr> movedEntities(
- EntityWrapperPtr theOld, StoragePtr theOldStorage,
- EntityWrapperPtr theNew, StoragePtr theNewStorage)
-{
- bool isFullyMoved = true;
- std::list<EntityWrapperPtr> aMoved;
- if (theOld->isEqual(theNew))
- return aMoved;
-
- std::list<EntityWrapperPtr> anOldSubs = theOld->subEntities();
- std::list<EntityWrapperPtr> aNewSubs = theNew->subEntities();
- std::list<EntityWrapperPtr>::const_iterator anOldIt = anOldSubs.begin();
- std::list<EntityWrapperPtr>::const_iterator aNewIt = aNewSubs.begin();
- for (; anOldIt != anOldSubs.end() && aNewIt != aNewSubs.end(); ++anOldIt, ++aNewIt) {
- std::list<EntityWrapperPtr> aMovedSubs = movedEntities(
- *anOldIt, theOldStorage, *aNewIt, theNewStorage);
- // check only the points to be moved (because arcs in PlaneGCS have scalar subs too)
- if ((*anOldIt)->type() == ENTITY_POINT &&
- (aMovedSubs.size() != 1 || aMovedSubs.front() != *anOldIt))
- isFullyMoved = false;
- aMoved.insert(aMoved.end(), aMovedSubs.begin(), aMovedSubs.end());
- }
- if (isFullyMoved) {
- aMoved.clear();
- aMoved.push_back(theOld);
- }
- return aMoved;
-}
-
-
-void SketchSolver_ConstraintMovement::getAttributes(
- ParameterWrapperPtr& theValue,
- std::vector<EntityWrapperPtr>& theAttributes)
-{
- // There will be build entities, according to the fixed feature, in the separate storage
- // to check whether any point is moved
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- StoragePtr anOtherStorage = aBuilder->createStorage(myGroupID);
- anOtherStorage->setSketch(myStorage->sketch());
- if (!anOtherStorage->update(myBaseFeature, myGroupID))
- return;
- EntityWrapperPtr aNewEntity = anOtherStorage->entity(myBaseFeature);
- EntityWrapperPtr anOldEntity = myStorage->entity(myBaseFeature);
-
- std::list<EntityWrapperPtr> aMoved;
- if (aNewEntity && anOldEntity)
- aMoved = movedEntities(anOldEntity, myStorage, aNewEntity, anOtherStorage);
- else {
- // get attributes moved
- std::list<AttributePtr> anAttrList =
- myBaseFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt) {
- aNewEntity = anOtherStorage->entity(*anIt);
- anOldEntity = myStorage->entity(*anIt);
- if (!aNewEntity || !anOldEntity)
- continue;
- std::list<EntityWrapperPtr> aMovedAttr = movedEntities(
- anOldEntity, myStorage, aNewEntity, anOtherStorage);
- aMoved.insert(aMoved.end(), aMovedAttr.begin(), aMovedAttr.end());
- }
- }
- theAttributes.clear();
- theAttributes.insert(theAttributes.begin(), aMoved.begin(), aMoved.end());
-}
-
-bool SketchSolver_ConstraintMovement::remove()
-{
- cleanErrorMsg();
- // Move fixed entities back to the current group
- std::vector<EntityWrapperPtr>::iterator aMoveIt = myMovedEntities.begin();
- for (; aMoveIt != myMovedEntities.end(); ++aMoveIt) {
- if ((*aMoveIt)->baseAttribute())
- myStorage->update((*aMoveIt)->baseAttribute(), myGroupID);
- else if ((*aMoveIt)->baseFeature())
- myStorage->update((*aMoveIt)->baseFeature(), myGroupID);
- }
-
- // Remove base feature
- if (myBaseFeature)
- myStorage->removeEntity(myBaseFeature);
- return true;
-}
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_ConstraintMovement.h
-// Created: 15 Jun 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_ConstraintMovement_H_
-#define SketchSolver_ConstraintMovement_H_
-
-#include "SketchSolver.h"
-#include <SketchSolver_ConstraintFixed.h>
-
-/** \class SketchSolver_ConstraintMovement
- * \ingroup Plugins
- * \brief Stores data to the Fixed constraint for the moved feature only
- */
-class SketchSolver_ConstraintMovement : public SketchSolver_ConstraintFixed
-{
-private:
- /// Creates constraint to manage the given constraint from plugin
- SketchSolver_ConstraintMovement(ConstraintPtr theConstraint)
- : SketchSolver_ConstraintFixed(theConstraint)
- {}
-
-public:
- /// Creates temporary constraint based on feature
- SketchSolver_ConstraintMovement(FeaturePtr theFeature)
- : SketchSolver_ConstraintFixed(theFeature)
- {}
-
- /// \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();
-
- /// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- /// (list of moved entities or attributes)
- virtual void getAttributes(ParameterWrapperPtr& theValue,
- std::vector<EntityWrapperPtr>& theAttributes);
-
-private:
- std::vector<EntityWrapperPtr> myMovedEntities; ///< list of entities that are moved
-};
-
-#endif
void SketchSolver_ConstraintMulti::getEntities(std::list<EntityWrapperPtr>& theEntities)
{
myAdjusted = false;
- DataPtr aData = myBaseConstraint->data();
// Lists of objects and number of copies
- AttributeRefListPtr anInitialRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
+ AttributeRefListPtr anInitialRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
myNumberOfObjects = anInitialRefList->size();
- myNumberOfCopies = aData->integer(nameNbObjects())->value() - 1;
+ myNumberOfCopies = myBaseConstraint->integer(nameNbObjects())->value() - 1;
if (myNumberOfCopies <= 0)
return;
- AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- aData->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ AttributeRefListPtr aRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
if (!aRefList || aRefList->size() == 0) {
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
return;
// the entity is not created, so it is a copy in "multi" constraint, force its creation
if (!myStorage->update(aFeature))
- myStorage->update(aFeature, myGroupID, true);
+ myStorage->update(aFeature, true);
theEntities.push_back(myStorage->entity(aFeature));
myFeatures.insert(aFeature);
for (int i = 0; i < myNumberOfCopies && anObjIt != anObjectList.end(); ++i, ++anObjIt) {
bool SketchSolver_ConstraintMulti::remove()
{
+ myStorage->unsubscribeUpdates(this);
+
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()));
+ AttributeRefListPtr anInitialRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_A());
AttributeIntegerPtr aNbObjects = myBaseConstraint->integer(nameNbObjects());
if (!anInitialRefList || !aNbObjects)
return; // the "Multi" constraint is in queue to remove
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()));
+ AttributeRefListPtr aRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
if (aRefList && aRefList->size() != 0) {
FeaturePtr aFeature;
std::list<ObjectPtr> anObjectList = aRefList->list();
if (isUpdated) {
remove();
process();
- return;
}
-
- // update derivative object
- updateLocal();
- if (isForce)
- myAdjusted = false;
- adjustConstraint();
}
void SketchSolver_ConstraintMulti::adjustConstraint()
{
- AttributeRefListPtr aRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- myBaseConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
+ AttributeRefListPtr aRefList =
+ myBaseConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
if (!aRefList || aRefList->size() == 0) {
myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
return;
}
FeaturePtr anOriginal, aFeature;
+ std::list<double>::iterator aXIt, aYIt;
+
std::list<ObjectPtr> anObjectList = aRefList->list();
std::list<ObjectPtr>::iterator anObjIt = anObjectList.begin();
while (anObjIt != anObjectList.end()) {
// Fill lists of coordinates of points composing a feature
std::list<double> aX, aY;
- std::list<double>::iterator aXIt, aYIt;
double aXCoord, aYCoord;
- EntityWrapperPtr anEntity = myStorage->entity(anOriginal);
- std::list<EntityWrapperPtr> aSubs = anEntity->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
- for (; aSIt != aSubs.end(); ++aSIt) {
- if ((*aSIt)->type() != ENTITY_POINT)
- continue;
- AttributePoint2DPtr aPoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>((*aSIt)->baseAttribute());
- if (aPoint) {
- aXCoord = aPoint->x();
- aYCoord = aPoint->y();
- } else {
- std::list<ParameterWrapperPtr> aParameters = (*aSIt)->parameters();
- aXCoord = aParameters.front()->value();
- aYCoord = aParameters.back()->value();
- }
- getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
+ std::list<AttributePtr> aPoints =
+ anOriginal->data()->attributes(GeomDataAPI_Point2D::typeId());
+ std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
+ for (; aPtIt != aPoints.end(); ++aPtIt) {
+ AttributePoint2DPtr aPoint2D = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
+ if (aPoint2D->isInitialized()) {
+ aXCoord = aPoint2D->x();
+ aYCoord = aPoint2D->y();
+ getRelative(aXCoord, aYCoord, aXCoord, aYCoord);
+ } else
+ aXCoord = aYCoord = 0;
+
aX.push_back(aXCoord);
aY.push_back(aYCoord);
}
aFeature = ModelAPI_Feature::feature(*anObjIt);
if (!aFeature)
continue;
- anEntity = myStorage->entity(aFeature);
-
- bool aWasBlocked = false;
- if (!anEntity || !myStorage->isEventsBlocked())
- aWasBlocked = aFeature->data()->blockSendAttributeUpdated(true);
-
- std::list<AttributePtr> aPoints;
- if (aFeature->getKind() == SketchPlugin_Arc::ID()) {
- aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::CENTER_ID()));
- aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::START_ID()));
- aPoints.push_back(aFeature->attribute(SketchPlugin_Arc::END_ID()));
- } else if (aFeature->getKind() == SketchPlugin_Line::ID()) {
- aPoints.push_back(aFeature->attribute(SketchPlugin_Line::START_ID()));
- aPoints.push_back(aFeature->attribute(SketchPlugin_Line::END_ID()));
- } else if (aFeature->getKind() == SketchPlugin_Circle::ID()) {
- aPoints.push_back(aFeature->attribute(SketchPlugin_Circle::CENTER_ID()));
- // update circle's radius
+
+ if (myIsEventsBlocked)
+ aFeature->data()->blockSendAttributeUpdated(true);
+
+ if (aFeature->getKind() == SketchPlugin_Circle::ID()) // update circle's radius
aFeature->real(SketchPlugin_Circle::RADIUS_ID())->setValue(
anOriginal->real(SketchPlugin_Circle::RADIUS_ID())->value());
- } else if (aFeature->getKind() == SketchPlugin_Point::ID() ||
- aFeature->getKind() == SketchPlugin_IntersectionPoint::ID())
- aPoints.push_back(aFeature->attribute(SketchPlugin_Point::COORD_ID()));
- std::list<AttributePtr>::iterator aPtIt = aPoints.begin();
- for (aXIt = aX.begin(), aYIt = aY.begin(); aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
+ aPoints = aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
+ for (aPtIt = aPoints.begin(), aXIt = aX.begin(), aYIt = aY.begin();
+ aPtIt != aPoints.end(); ++aXIt, ++aYIt, ++aPtIt) {
+ if (!(*aPtIt)->isInitialized())
+ continue;
transformRelative(*aXIt, *aYIt);
getAbsolute(*aXIt, *aYIt, aXCoord, aYCoord);
- std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
+ AttributePoint2DPtr aPoint2D =
std::dynamic_pointer_cast<GeomDataAPI_Point2D>(*aPtIt);
aPoint2D->setValue(aXCoord, aYCoord);
}
-
- // update feature in the storage if it is used by another constraints
- if (anEntity)
- myStorage->update(aFeature);
- else { // update attributes, if they exist in the storage
- for (aPtIt = aPoints.begin(); aPtIt != aPoints.end(); ++aPtIt) {
- EntityWrapperPtr aPntEnt = myStorage->entity(*aPtIt);
- if (aPntEnt)
- myStorage->update(*aPtIt);
- }
- }
-
- if (!anEntity || !myStorage->isEventsBlocked())
- aFeature->data()->blockSendAttributeUpdated(aWasBlocked);
}
}
myAdjusted = true;
}
-bool SketchSolver_ConstraintMulti::isUsed(FeaturePtr theFeature) const
+void SketchSolver_ConstraintMulti::notify(const FeaturePtr& theFeature,
+ PlaneGCSSolver_Update*)
{
- return theFeature && (myFeatures.find(theFeature) != myFeatures.end() ||
- SketchSolver_Constraint::isUsed(theFeature));
+ if (myFeatures.find(theFeature) == myFeatures.end())
+ return; // the feature is not used by constraint => nothing to update
+
+ // update derivative object
+ updateLocal();
+ myAdjusted = false;
+ adjustConstraint();
}
-bool SketchSolver_ConstraintMulti::isUsed(AttributePtr theAttribute) const
+void SketchSolver_ConstraintMulti::blockEvents(bool isBlocked)
{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
- else
- anAttribute = aRefAttr->attr();
- }
- if (!anAttribute)
- return false;
+ myIsEventsBlocked = isBlocked;
+
+ std::set<FeaturePtr>::iterator anIt = myFeatures.begin();
+ for (; anIt != myFeatures.end(); ++anIt)
+ (*anIt)->data()->blockSendAttributeUpdated(isBlocked);
- FeaturePtr anOwner = ModelAPI_Feature::feature(anAttribute->owner());
- return myFeatures.find(anOwner) != myFeatures.end();
+ SketchSolver_Constraint::blockEvents(isBlocked);
}
SketchSolver_Constraint(theConstraint),
myNumberOfObjects(0),
myNumberOfCopies(0),
+ myIsFullValue(false),
myAdjusted(false),
- myIsFullValue(false)
+ myIsEventsBlocked(false)
{}
/// \brief Update constraint
- virtual void update();
- /// \brief Update constraint
- void update(bool isForce);
+ virtual void update() override;
+
+ /// \brief Notify this object about the feature is changed somewhere
+ virtual void notify(const FeaturePtr& theFeature, PlaneGCSSolver_Update*) override;
/// \brief Tries to remove constraint
/// \return \c false, if current constraint contains another SketchPlugin
/// constraints (like for multiple coincidence)
- virtual bool remove();
+ virtual bool remove() override;
- /// \brief Check the feature is a source or a copy of Multi-constraint
- virtual bool isUsed(FeaturePtr theFeature) const;
- /// \brief Check the attribute is used in Multi-constraint
- virtual bool isUsed(AttributePtr theAttribute) const;
+ /// \brief Block or unblock events from this constraint
+ virtual void blockEvents(bool isBlocked) override;
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
- virtual void process()
+ virtual void process() override
{ /* do nothing here */ }
- /// \brief Collect entities which translated or rotated (not their copies)
+ /// \brief Collect entities which are translated or rotated (not their copies)
void getEntities(std::list<EntityWrapperPtr>& theEntities);
/// \brief Generate list of attributes of constraint in order useful for SolveSpace constraints
- /// \param[out] theValue numerical characteristic of constraint (e.g. distance)
- /// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes)
+ virtual void getAttributes(EntityWrapperPtr&, std::vector<EntityWrapperPtr>&) override
{ /* do nothing here */ }
/// \brief This method is used in derived objects to check consistence of constraint.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
/// \brief Update parameters of derived classes
virtual void updateLocal() = 0;
/// list of features and their copies to find whether some of them are disappeared
std::set<FeaturePtr> myFeatures;
+
+ bool myIsEventsBlocked;
};
#endif
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_AttributeBuilder.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+#include <PlaneGCSSolver_ScalarWrapper.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
+
#include <SketchPlugin_MultiRotation.h>
#include <ModelAPI_AttributeString.h>
-#include <math.h>
+#include <cmath>
void SketchSolver_ConstraintMultiRotation::getAttributes(
- EntityWrapperPtr& theCenter, double& theAngle,
+ EntityWrapperPtr& theCenter, EntityWrapperPtr& theAngle,
bool& theFullValue, std::list<EntityWrapperPtr>& theEntities)
{
- DataPtr aData = myBaseConstraint->data();
- theAngle = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- aData->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+ AttributePtr anAngleAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID());
+ PlaneGCSSolver_AttributeBuilder aValueBuilder;
+ theAngle = aValueBuilder.createAttribute(anAngleAttr);
+ myStorage->addEntity(anAngleAttr, theAngle);
- AttributePtr aCenterAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
+ AttributePtr aCenterAttr = myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID());
if (!aCenterAttr || !aCenterAttr->isInitialized()) {
myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
return;
myStorage->update(aCenterAttr);
theCenter = myStorage->entity(aCenterAttr);
- AttributeStringPtr aMethodTypeAttr = aData->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
+ AttributeStringPtr aMethodTypeAttr =
+ myBaseConstraint->string(SketchPlugin_MultiRotation::ANGLE_TYPE());
theFullValue = aMethodTypeAttr->value() != "SingleAngle";
getEntities(theEntities);
void SketchSolver_ConstraintMultiRotation::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
- /// TODO: Put error message here
+ if (!myBaseConstraint || !myStorage) {
+ // Not enough parameters are assigned
return;
}
+ EntityWrapperPtr anAngle;
EntityWrapperPtr aRotationCenter;
bool isFullValue;
std::list<EntityWrapperPtr> aBaseEntities;
- getAttributes(aRotationCenter, myAngle, isFullValue, aBaseEntities);
+ getAttributes(aRotationCenter, anAngle, isFullValue, aBaseEntities);
if (!myErrorMsg.empty())
return;
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aRotConstraints;
-
- std::list<EntityWrapperPtr>::iterator anEntIt = aBaseEntities.begin();
- for (; anEntIt != aBaseEntities.end(); ++anEntIt) {
- std::list<ConstraintWrapperPtr> aNewConstraints =
- aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
- myAngle, isFullValue, aRotationCenter, EntityWrapperPtr(),
- std::list<EntityWrapperPtr>(1, *anEntIt));
- aRotConstraints.insert(aRotConstraints.end(), aNewConstraints.begin(), aNewConstraints.end());
- }
- myStorage->addConstraint(myBaseConstraint, aRotConstraints);
-
+ ScalarWrapperPtr anAngleVal = std::dynamic_pointer_cast<PlaneGCSSolver_ScalarWrapper>(anAngle);
+ myAngle = anAngleVal->value();
myAdjusted = false;
adjustConstraint();
+
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
}
void SketchSolver_ConstraintMultiRotation::updateLocal()
{
- double aValue = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- myBaseConstraint->attribute(SketchPlugin_MultiRotation::ANGLE_ID()))->value();
+ double aValue = myBaseConstraint->real(SketchPlugin_MultiRotation::ANGLE_ID())->value();
if (fabs(myAngle - aValue) > tolerance)
myAdjusted = false;
// update angle value
if (isMethodChanged)
myIsFullValue = aFullValue;
- if (aCenterPointChanged || isMethodChanged) {
- DataPtr aData = myBaseConstraint->data();
- std::list<ConstraintWrapperPtr> aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstraints.begin(),
- aLast = aConstraints.end();
- std::list<EntityWrapperPtr> anEntities;
- for (; anIt != aLast; anIt++) {
- ConstraintWrapperPtr aConstraint = *anIt;
- aConstraint->setIsFullValue(myIsFullValue);
- if (aCenterPointChanged) {
- anEntities.clear();
- const std::list<EntityWrapperPtr>& aConstraintEntities = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aConstraintEntities.begin(),
- aSLast = aConstraintEntities.end();
- EntityWrapperPtr aCenterPointEntity = *aSIt++;
- if (aCenterPointChanged) {
- AttributePtr aCenterPointAttr = aData->attribute(SketchPlugin_MultiRotation::CENTER_ID());
- myStorage->update(aCenterPointAttr);
- aCenterPointEntity = myStorage->entity(aCenterPointAttr);
- }
- anEntities.push_back(aCenterPointEntity);
-
- for (; aSIt != aSLast; ++aSIt)
- anEntities.push_back(*aSIt);
-
- aConstraint->setEntities(anEntities);
- }
- }
- myStorage->addConstraint(myBaseConstraint, aConstraints);
-
+ if (aCenterPointChanged || isMethodChanged)
myAdjusted = false;
- }
}
void SketchSolver_ConstraintMultiRotation::adjustConstraint()
return;
}
- const std::list<ConstraintWrapperPtr>& aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator aCIt = aConstraints.begin();
- for (; aCIt != aConstraints.end(); ++aCIt)
- (*aCIt)->setValue(myAngle);
-
// Obtain coordinates of rotation center
- EntityWrapperPtr aRotCenter = myStorage->entity(
- myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID()));
- std::list<ParameterWrapperPtr> aParams = aRotCenter->parameters();
- myCenterCoord[0] = aParams.front()->value();
- myCenterCoord[1] = aParams.back()->value();
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aRotCenter =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
+ myBaseConstraint->attribute(SketchPlugin_MultiRotation::CENTER_ID())));
+ GCSPointPtr aCenterPoint = aRotCenter->point();
+ myCenterCoord[0] = *(aCenterPoint->x);
+ myCenterCoord[1] = *(aCenterPoint->y);
double anAngleValue = myAngle;
if (myIsFullValue && myNumberOfCopies > 0)
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
- virtual void process();
+ virtual void process() override;
/// \brief Generate list of rotated entities
/// \param[out] theCenter central point of rotation
/// \param[out] theAngle rotation angle
/// \param[out] theFullValue applying translation using the disstance as a full or single value
/// \param[out] theEntities list of base entities
- void getAttributes(EntityWrapperPtr& theCenter, double& theAngle, bool& theFullValue,
+ void getAttributes(EntityWrapperPtr& theCenter,
+ EntityWrapperPtr& theAngle,
+ bool& theFullValue,
std::list<EntityWrapperPtr>& theEntities);
/// \brief This method is used in derived objects to check consistence of constraint.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
/// \brief Update parameters (called from base class)
- virtual void updateLocal();
+ virtual void updateLocal() override;
private:
/// \brief Convert absolute coordinates to relative coordinates
- virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+ virtual void getRelative(double theAbsX, double theAbsY,
+ double& theRelX, double& theRelY) override;
/// \brief Convert relative coordinates to absolute coordinates
- virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+ virtual void getAbsolute(double theRelX, double theRelY,
+ double& theAbsX, double& theAbsY) override;
/// \brief Apply transformation for relative coordinates
- virtual void transformRelative(double& theX, double& theY);
+ virtual void transformRelative(double& theX, double& theY) override;
/// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
- virtual const std::string& nameNbObjects();
+ virtual const std::string& nameNbObjects() override;
private:
AttributePoint2DPtr myCenterPointAttribute; ///< a center of rotation
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_PointWrapper.h>
+
#include <SketchPlugin_MultiTranslation.h>
#include <ModelAPI_AttributeString.h>
void SketchSolver_ConstraintMultiTranslation::process()
{
cleanErrorMsg();
- if (!myBaseConstraint || !myStorage || myGroupID == GID_UNKNOWN) {
- /// TODO: Put error message here
+ if (!myBaseConstraint || !myStorage) {
+ // Not enough parameters are assigned
return;
}
if (!myErrorMsg.empty())
return;
- AttributeStringPtr aMethodTypeAttr =
- myBaseConstraint->data()->string(SketchPlugin_MultiTranslation::VALUE_TYPE());
-
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::list<ConstraintWrapperPtr> aTransConstraints;
-
- std::list<EntityWrapperPtr>::iterator anEntIt = aBaseEntities.begin();
- for (; anEntIt != aBaseEntities.end(); ++anEntIt) {
- std::list<ConstraintWrapperPtr> aNewConstraints =
- aBuilder->createConstraint(myBaseConstraint, myGroupID, mySketchID, myType,
- 0.0, aFullValue, aStartPoint, aEndPoint, std::list<EntityWrapperPtr>(1, *anEntIt));
- aTransConstraints.insert(aTransConstraints.end(),
- aNewConstraints.begin(), aNewConstraints.end());
- }
-
- myStorage->addConstraint(myBaseConstraint, aTransConstraints);
-
myAdjusted = false;
adjustConstraint();
+
+ myStorage->subscribeUpdates(this, PlaneGCSSolver_UpdateFeature::GROUP());
}
const std::string& SketchSolver_ConstraintMultiTranslation::nameNbObjects()
if (isMethodChanged)
myIsFullValue = aFullValue;
- if (aStartPointChanged || anEndPointChanged || isMethodChanged) {
- DataPtr aData = myBaseConstraint->data();
- std::list<ConstraintWrapperPtr> aConstraints = myStorage->constraint(myBaseConstraint);
- std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstraints.begin(),
- aLast = aConstraints.end();
- std::list<EntityWrapperPtr> anEntities;
- for (; anIt != aLast; anIt++) {
- ConstraintWrapperPtr aConstraint = *anIt;
- aConstraint->setIsFullValue(myIsFullValue);
- anEntities.clear();
-
- const std::list<EntityWrapperPtr>& aConstraintEntities = aConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aConstraintEntities.begin(),
- aSLast = aConstraintEntities.end();
- EntityWrapperPtr aStartEntity = *aSIt++;
- if (aStartPointChanged) {
- AttributePtr aStartPointAttr =
- aData->attribute(SketchPlugin_MultiTranslation::START_POINT_ID());
- myStorage->update(aStartPointAttr);
- aStartEntity = myStorage->entity(aStartPointAttr);
- }
- anEntities.push_back(aStartEntity);
-
- EntityWrapperPtr anEndEntity = *aSIt++;
- if (anEndPointChanged) {
- AttributePtr anEndPointAttr =
- aData->attribute(SketchPlugin_MultiTranslation::END_POINT_ID());
- myStorage->update(anEndPointAttr);
- anEndEntity = myStorage->entity(anEndPointAttr);
- }
- anEntities.push_back(anEndEntity);
-
- for (; aSIt != aSLast; ++aSIt)
- anEntities.push_back(*aSIt);
-
- aConstraint->setEntities(anEntities);
- }
- myStorage->addConstraint(myBaseConstraint, aConstraints);
-
+ if (aStartPointChanged || anEndPointChanged || isMethodChanged)
myAdjusted = false;
- }
}
void SketchSolver_ConstraintMultiTranslation::adjustConstraint()
return;
// Obtain delta between start and end points of translation
- EntityWrapperPtr aStart = myStorage->entity(
- myBaseConstraint->attribute(SketchPlugin_MultiTranslation::START_POINT_ID()));
- std::list<ParameterWrapperPtr> aStartParams = aStart->parameters();
- EntityWrapperPtr aEnd = myStorage->entity(
- myBaseConstraint->attribute(SketchPlugin_MultiTranslation::END_POINT_ID()));
- std::list<ParameterWrapperPtr> aEndParams = aEnd->parameters();
-
- myDelta[0] = aEndParams.front()->value() - aStartParams.front()->value();
- myDelta[1] = aEndParams.back()->value() - aStartParams.back()->value();
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aStartWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
+ myBaseConstraint->attribute(SketchPlugin_MultiTranslation::START_POINT_ID())));
+ std::shared_ptr<PlaneGCSSolver_PointWrapper> aEndWrapper =
+ std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(myStorage->entity(
+ myBaseConstraint->attribute(SketchPlugin_MultiTranslation::END_POINT_ID())));
+
+ GCSPointPtr aStart = aStartWrapper->point();
+ GCSPointPtr aEnd = aEndWrapper->point();
+
+ myDelta[0] = *(aEnd->x) - *(aStart->x);
+ myDelta[1] = *(aEnd->y) - *(aStart->y);
if (myIsFullValue && myNumberOfCopies > 0) {
myDelta[0] /= myNumberOfCopies;
protected:
/// \brief Converts SketchPlugin constraint to a list of SolveSpace constraints
- virtual void process();
+ virtual void process() override;
/// \brief Generate list of translated entities
/// \param[out] theStartPoint start point of translation
bool& theFullValue, std::list<EntityWrapperPtr>& theEntities);
/// \brief This method is used in derived objects to check consistence of constraint.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
/// \brief Update parameters (called from base class)
- virtual void updateLocal();
+ virtual void updateLocal() override;
private:
/// \brief Convert absolute coordinates to relative coordinates
- virtual void getRelative(double theAbsX, double theAbsY, double& theRelX, double& theRelY);
+ virtual void getRelative(double theAbsX, double theAbsY,
+ double& theRelX, double& theRelY) override;
/// \brief Convert relative coordinates to absolute coordinates
- virtual void getAbsolute(double theRelX, double theRelY, double& theAbsX, double& theAbsY);
+ virtual void getAbsolute(double theRelX, double theRelY,
+ double& theAbsX, double& theAbsY) override;
/// \brief Apply transformation for relative coordinates
- virtual void transformRelative(double& theX, double& theY);
+ virtual void transformRelative(double& theX, double& theY) override;
/// \brief Returns name of NUMBER_OF_COPIES parameter for corresponding feature
- virtual const std::string& nameNbObjects();
+ virtual const std::string& nameNbObjects() override;
private:
AttributePoint2DPtr myStartPointAttribute;
#include <GeomAPI_Pnt2d.h>
#include <SketchPlugin_Circle.h>
+#include <SketchPlugin_ConstraintCoincidence.h>
#include <cmath>
-/// \brief Check whether the entities has only one shared point
-static bool hasSingleCoincidence(EntityWrapperPtr theEntity1, EntityWrapperPtr theEntity2)
+/// \brief Check whether the entities has only one shared point or less
+static bool hasSingleCoincidence(FeaturePtr theFeature1, FeaturePtr theFeature2)
{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
-
- const std::list<EntityWrapperPtr>& aPoints1 = theEntity1->subEntities();
- const std::list<EntityWrapperPtr>& aPoints2 = theEntity2->subEntities();
-
- std::list<EntityWrapperPtr>::const_iterator aStartIt1 = aPoints1.begin();
- if (theEntity1->type() == ENTITY_ARC) ++aStartIt1; // skip center of arc
- std::list<EntityWrapperPtr>::const_iterator aStartIt2 = aPoints2.begin();
- if (theEntity2->type() == ENTITY_ARC) ++aStartIt2; // skip center of arc
-
- int aNbCoinc = 0;
- std::list<EntityWrapperPtr>::const_iterator anIt1, anIt2;
- for (anIt1 = aStartIt1; anIt1 != aPoints1.end(); ++anIt1) {
- if ((*anIt1)->type() != ENTITY_POINT)
- continue;
- std::shared_ptr<GeomAPI_Pnt2d> aPt1 = aBuilder->point(*anIt1);
- for (anIt2 = aStartIt2; anIt2 != aPoints2.end(); ++anIt2) {
- if ((*anIt2)->type() != ENTITY_POINT)
- continue;
- std::shared_ptr<GeomAPI_Pnt2d> aPt2 = aBuilder->point(*anIt2);
- if (aPt1->distance(aPt2) < tolerance)
- ++aNbCoinc;
- }
+ const std::set<AttributePtr>& aRefs1 = theFeature1->data()->refsToMe();
+ const std::set<AttributePtr>& aRefs2 = theFeature2->data()->refsToMe();
+
+ // collect all shared coincidendes
+ std::set<FeaturePtr> aCoincidences;
+ std::set<AttributePtr>::const_iterator anIt;
+ for (anIt = aRefs1.begin(); anIt != aRefs1.end(); ++anIt) {
+ FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aRef && aRef->getKind() == SketchPlugin_ConstraintCoincidence::ID())
+ aCoincidences.insert(aRef);
}
- return aNbCoinc == 1;
+ for (anIt = aRefs2.begin(); anIt != aRefs2.end(); ++anIt) {
+ FeaturePtr aRef = ModelAPI_Feature::feature((*anIt)->owner());
+ if (aRef)
+ aCoincidences.erase(aRef);
+ }
+
+ return aCoincidences.size() <= 1;
}
/// \brief Check if two connected arcs have centers
void SketchSolver_ConstraintTangent::getAttributes(
- double& theValue,
+ EntityWrapperPtr& theValue,
std::vector<EntityWrapperPtr>& theAttributes)
{
SketchSolver_Constraint::getAttributes(theValue, theAttributes);
return;
}
- if (myType == CONSTRAINT_TANGENT_ARC_LINE &&
- !hasSingleCoincidence(theAttributes[2], theAttributes[3]))
- myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
+ if (myType == CONSTRAINT_TANGENT_ARC_LINE) {
+ AttributeRefAttrPtr aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A());
+ FeaturePtr aFeature1 = ModelAPI_Feature::feature(aRefAttr->object());
+ aRefAttr = myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B());
+ FeaturePtr aFeature2 = ModelAPI_Feature::feature(aRefAttr->object());
+
+ if (!hasSingleCoincidence(aFeature1, aFeature2))
+ myErrorMsg = SketchSolver_Error::TANGENCY_FAILED();
+ }
if (isSwap) {
EntityWrapperPtr aTemp = theAttributes[2];
void SketchSolver_ConstraintTangent::adjustConstraint()
{
- if (myType == CONSTRAINT_TANGENT_CIRCLE_LINE) {
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
- AttributePtr aCircleCenter = aConstraint->entities().front()->baseAttribute();
- if (!aCircleCenter)
- return;
- FeaturePtr aCircle = ModelAPI_Feature::feature(aCircleCenter->owner());
- AttributeDoublePtr aRadius = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
- aCircle->attribute(SketchPlugin_Circle::RADIUS_ID()));
-
- if (fabs(aRadius->value()) == fabs(aConstraint->value()))
- return;
-
- aConstraint->setValue(aRadius->value());
-
- // Adjust the sign of constraint value
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- aBuilder->adjustConstraint(aConstraint);
- myStorage->addConstraint(myBaseConstraint, aConstraint);
- }
- else if (myType == CONSTRAINT_TANGENT_ARC_ARC) {
- ConstraintWrapperPtr aConstraint = myStorage->constraint(myBaseConstraint).front();
- if (isArcArcInternal != isInternalTangency(
- aConstraint->entities().front(), aConstraint->entities().back())) {
+ if (myType == CONSTRAINT_TANGENT_ARC_ARC) {
+ EntityWrapperPtr anEntity1 =
+ myStorage->entity(myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_A()));
+ EntityWrapperPtr anEntity2 =
+ myStorage->entity(myBaseConstraint->refattr(SketchPlugin_Constraint::ENTITY_B()));
+
+ if (isArcArcInternal != isInternalTangency(anEntity1, anEntity2)) {
// fully rebuld constraint, because it is unable to access attributes of PlaneGCS constraint
remove();
process();
/// \brief Generate list of attributes of constraint in order useful for constraints
/// \param[out] theValue numerical characteristic of constraint (e.g. distance)
/// \param[out] theAttributes list of attributes to be filled
- virtual void getAttributes(double& theValue, std::vector<EntityWrapperPtr>& theAttributes);
+ virtual void getAttributes(EntityWrapperPtr& theValue,
+ std::vector<EntityWrapperPtr>& theAttributes) override;
/// \brief This method is used in derived objects to check consistency of constraint.
/// E.g. the distance between line and point may be signed.
- virtual void adjustConstraint();
+ virtual void adjustConstraint() override;
private:
bool isArcArcInternal;
// Author: Artem ZHIDKOV
#include "SketchSolver_Group.h"
-
-#include <SketchSolver_Constraint.h>
-#include <SketchSolver_ConstraintCoincidence.h>
-#include <SketchSolver_ConstraintMulti.h>
#include <SketchSolver_Error.h>
#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_Solver.h>
+
#include <Events_InfoMessage.h>
-#include <Events_Loop.h>
#include <ModelAPI_AttributeString.h>
#include <ModelAPI_Events.h>
-#include <ModelAPI_Session.h>
-#include <ModelAPI_Validator.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_ConstraintAngle.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
-#include <SketchPlugin_ConstraintDistance.h>
-#include <SketchPlugin_ConstraintEqual.h>
-#include <SketchPlugin_ConstraintHorizontal.h>
-#include <SketchPlugin_ConstraintLength.h>
-#include <SketchPlugin_ConstraintFillet.h>
-#include <SketchPlugin_ConstraintMirror.h>
-#include <SketchPlugin_ConstraintParallel.h>
-#include <SketchPlugin_ConstraintPerpendicular.h>
-#include <SketchPlugin_ConstraintRadius.h>
#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintSplit.h>
-#include <SketchPlugin_ConstraintTangent.h>
-#include <SketchPlugin_ConstraintVertical.h>
-#include <SketchPlugin_MultiRotation.h>
-#include <SketchPlugin_MultiTranslation.h>
-
-#include <math.h>
-#include <assert.h>
-
-
-/// \brief This class is used to give unique index to the groups
-class GroupIndexer
-{
-public:
- /// \brief Return vacant index
- static GroupID NEW_GROUP() { return ++myGroupIndex; }
- /// \brief Removes the index
- static void REMOVE_GROUP(const GroupID& theIndex) {
- if (myGroupIndex == theIndex)
- myGroupIndex--;
- }
-
-private:
- GroupIndexer() {};
-
- static GroupID myGroupIndex; ///< index of the group
-};
-
-GroupID GroupIndexer::myGroupIndex = GID_OUTOFGROUP;
static void sendMessage(const char* theMessageName)
// ========= SketchSolver_Group ===============
// ========================================================
-SketchSolver_Group::SketchSolver_Group(
- std::shared_ptr<ModelAPI_CompositeFeature> theWorkplane)
- : myID(GroupIndexer::NEW_GROUP()),
- myPrevResult(STATUS_UNKNOWN)
+SketchSolver_Group::SketchSolver_Group(const CompositeFeaturePtr& theWorkplane)
+ : mySketch(theWorkplane),
+ myPrevResult(STATUS_UNKNOWN),
+ myIsEventsBlocked(false)
{
- // Initialize workplane
- myWorkplaneID = EID_UNKNOWN;
- addWorkplane(theWorkplane);
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
+ mySketchSolver = aBuilder->createSolver();
+ myStorage = aBuilder->createStorage(mySketchSolver);
}
SketchSolver_Group::~SketchSolver_Group()
{
myConstraints.clear();
- GroupIndexer::REMOVE_GROUP(myID);
// send the message that there is no more conflicting constraints
if (!myConflictingConstraints.empty()) {
sendMessage(EVENT_SOLVER_REPAIRED, myConflictingConstraints);
}
}
-// ============================================================================
-// Function: isBaseWorkplane
-// Class: SketchSolver_Group
-// Purpose: verify the group is based on the given workplane
-// ============================================================================
-bool SketchSolver_Group::isBaseWorkplane(CompositeFeaturePtr theWorkplane) const
-{
- return theWorkplane == mySketch;
-}
-
-// ============================================================================
-// Function: isInteract
-// Class: SketchSolver_Group
-// Purpose: verify are there any entities in the group used by given constraint
-// ============================================================================
-bool SketchSolver_Group::isInteract(FeaturePtr theFeature) const
-{
- // Empty group interacts with everything
- if (isEmpty())
- return true;
- // Check interaction with the storage
- bool isInteracted = myStorage->isInteract(theFeature);
- ConstraintConstraintMap::const_iterator anIt = myConstraints.begin();
- for (; !isInteracted && anIt != myConstraints.end(); ++anIt)
- if (anIt->first->getKind() == SketchPlugin_MultiRotation::ID() ||
- anIt->first->getKind() == SketchPlugin_MultiTranslation::ID()) {
- isInteracted = anIt->second->isUsed(theFeature);
- if (isInteracted)
- break;
- // if theFeature is a constraint, check its attributes
- ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
- if (!aConstraint)
- continue;
- for (int i = 0; i < 4 && !isInteracted; ++i) {
- AttributeRefAttrPtr aRefAttr = aConstraint->refattr(aConstraint->ATTRIBUTE(i));
- if (!aRefAttr)
- continue;
- isInteracted = anIt->second->isUsed((AttributePtr)aRefAttr);
- }
- }
- return isInteracted;
-}
-
// ============================================================================
// Function: changeConstraint
// Class: SketchSolver_Group
bool SketchSolver_Group::changeConstraint(
std::shared_ptr<SketchPlugin_Constraint> theConstraint)
{
- // There is no workplane yet, something wrong
- if (myWorkplaneID == EID_UNKNOWN)
- return false;
-
- if (!theConstraint || !theConstraint->data())
- return false;
-
- if (!checkFeatureValidity(theConstraint))
- return false;
-
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- myStorage->blockEvents(true);
-
bool isNewConstraint = myConstraints.find(theConstraint) == myConstraints.end();
if (isNewConstraint) {
+ BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
// Add constraint to the current group
SolverConstraintPtr aConstraint = aBuilder->createConstraint(theConstraint);
if (!aConstraint)
return false;
- aConstraint->process(myStorage, getId(), getWorkplaneId());
+ aConstraint->process(myStorage, myIsEventsBlocked);
if (!aConstraint->error().empty()) {
if (aConstraint->error() == SketchSolver_Error::NOT_INITIALIZED())
return false; // some attribute are not initialized yet, don't show message
Events_InfoMessage("SketchSolver_Group", aConstraint->error(), this).send();
}
myConstraints[theConstraint] = aConstraint;
-
- if (theConstraint->getKind() == SketchPlugin_ConstraintCoincidence::ID())
- notifyCoincidenceChanged(myConstraints[theConstraint]);
}
else
myConstraints[theConstraint]->update();
-
- // Fix mirror line
- if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- theConstraint->attribute(SketchPlugin_ConstraintMirror::ENTITY_A()));
- if (aRefAttr && aRefAttr->isObject()) {
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(
- ModelAPI_Feature::feature(aRefAttr->object()));
- if (aFeature) {
- SolverConstraintPtr aConstraint = aBuilder->createFixedConstraint(aFeature);
- if (aConstraint) {
- aConstraint->process(myStorage, getId(), getWorkplaneId());
- setTemporary(aConstraint);
- }
- }
- }
- }
return true;
}
-// Update constraints if they contain specific feature
-static void updateMultiConstraints(ConstraintConstraintMap& theConstraints, FeaturePtr theFeature)
-{
- ConstraintConstraintMap::iterator aCIt = theConstraints.begin();
- for (; aCIt != theConstraints.end(); ++aCIt) {
- SketchSolver_ConstraintType aType = aCIt->second->getType();
- if ((aType == CONSTRAINT_MULTI_ROTATION ||
- aType == CONSTRAINT_MULTI_TRANSLATION)
- && aCIt->second->isUsed(theFeature))
- std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
- else if ((aType == CONSTRAINT_TANGENT_CIRCLE_LINE || aType == CONSTRAINT_TANGENT_ARC_ARC ||
- aType == CONSTRAINT_SYMMETRIC || aType == CONSTRAINT_ANGLE)
- && aCIt->second->isUsed(theFeature))
- aCIt->second->update();
- }
-}
-
-// Recalculate slave features of the Multi constraints
-static void updateMultiConstraints(ConstraintConstraintMap& theConstraints)
-{
- ConstraintConstraintMap::iterator aCIt = theConstraints.begin();
- for (; aCIt != theConstraints.end(); ++aCIt) {
- SketchSolver_ConstraintType aType = aCIt->second->getType();
- if ((aType == CONSTRAINT_MULTI_ROTATION ||
- aType == CONSTRAINT_MULTI_TRANSLATION))
- std::dynamic_pointer_cast<SketchSolver_ConstraintMulti>(aCIt->second)->update(true);
- }
-}
-
bool SketchSolver_Group::updateFeature(FeaturePtr theFeature)
{
- if (!checkFeatureValidity(theFeature))
- return false;
-
- bool isBlocked = myStorage->isEventsBlocked();
- if (!isBlocked)
- myStorage->blockEvents(true);
-
- myStorage->refresh(true);
- bool isUpdated = myStorage->update(theFeature);
-
- updateMultiConstraints(myConstraints, theFeature);
-
- // events were not blocked before, the feature has not been updated,
- // so it is necessary to revert blocking
- if (!isUpdated && !isBlocked)
- myStorage->blockEvents(false);
- return isUpdated;
+ return myStorage->update(theFeature);
}
bool SketchSolver_Group::moveFeature(FeaturePtr theFeature)
{
BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- // Firstly, revert changes in the fixed entities
- myStorage->blockEvents(true);
- myStorage->refresh(true);
-
- // Secondly, search attributes of the feature in the list of the Multi constraints and update them
- updateMultiConstraints(myConstraints, theFeature);
-
- // Then, create temporary Fixed constraint
+ // Create temporary Fixed constraint
SolverConstraintPtr aConstraint = aBuilder->createMovementConstraint(theFeature);
if (!aConstraint)
return false;
- aConstraint->process(myStorage, getId(), getWorkplaneId());
+ aConstraint->process(myStorage, myIsEventsBlocked);
if (aConstraint->error().empty())
setTemporary(aConstraint);
+ else
+ myStorage->notify(theFeature);
- // Workaround to process arcs.
- // When move unconstrained arc, add temporary constraint to fix radius.
- if (theFeature->getKind() == SketchPlugin_Arc::ID()) {
- bool hasDup = myStorage->hasDuplicatedConstraint();
- SolverConstraintPtr aFixedRadius = aBuilder->createFixedArcRadiusConstraint(theFeature);
- if (aFixedRadius) {
- aFixedRadius->process(myStorage, getId(), getWorkplaneId());
- hasDup = myStorage->hasDuplicatedConstraint() && !hasDup;
- if (aFixedRadius->error().empty() && !hasDup)
- setTemporary(aFixedRadius);
- else
- aFixedRadius->remove();
- }
- }
- return true;
-}
-
-// ============================================================================
-// Function: addWorkplane
-// Class: SketchSolver_Group
-// Purpose: create workplane for the group
-// ============================================================================
-bool SketchSolver_Group::addWorkplane(CompositeFeaturePtr theSketch)
-{
- if (myWorkplaneID != EID_UNKNOWN || theSketch->getKind() != SketchPlugin_Sketch::ID())
- return false; // the workplane already exists or the function parameter is not Sketch
-
- mySketch = theSketch;
- if (!updateWorkplane()) {
- mySketch = CompositeFeaturePtr();
- return false;
- }
return true;
}
-// ============================================================================
-// Function: updateWorkplane
-// Class: SketchSolver_Group
-// Purpose: update parameters of workplane
-// ============================================================================
-bool SketchSolver_Group::updateWorkplane()
-{
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- if (!myStorage) // Create storage if not exists
- myStorage = aBuilder->createStorage(getId());
-
- // sketch should be unchanged, set it out of current group
- bool isUpdated = myStorage->update(FeaturePtr(mySketch), GID_OUTOFGROUP);
- if (isUpdated) {
- EntityWrapperPtr anEntity = myStorage->entity(FeaturePtr(mySketch));
- myWorkplaneID = anEntity->id();
- }
- return isUpdated;
-}
-
// ============================================================================
// Function: resolveConstraints
// Class: SketchSolver_Group
bool isGroupEmpty = isEmpty() && myStorage->isEmpty();
if (myStorage->isNeedToResolve() &&
(!isGroupEmpty || !myConflictingConstraints.empty() || myPrevResult == STATUS_FAILED)) {
- if (!mySketchSolver)
- mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
+//// if (!mySketchSolver)
+//// mySketchSolver = SketchSolver_Manager::instance()->builder()->createSolver();
- mySketchSolver->setGroup(myID);
- mySketchSolver->calculateFailedConstraints(false);
- myStorage->initializeSolver(mySketchSolver);
- mySketchSolver->prepare();
+//// mySketchSolver->calculateFailedConstraints(false);
+ myStorage->initializeSolver();
+//// mySketchSolver->prepare();
SketchSolver_SolveStatus aResult = STATUS_OK;
try {
- if (myStorage->hasDuplicatedConstraint())
- aResult = STATUS_INCONSISTENT;
- else if (!isGroupEmpty) {
+ if (!isGroupEmpty) {
// To avoid overconstraint situation, we will remove temporary constraints one-by-one
// and try to find the case without overconstraint
bool isLastChance = false;
removeTemporaryConstraints();
mySketchSolver->calculateFailedConstraints(true); // something failed => need to find it
- myStorage->initializeSolver(mySketchSolver);
+ myStorage->initializeSolver();
}
}
} catch (...) {
if (aResult == STATUS_OK || aResult == STATUS_EMPTYSET) {
myStorage->setNeedToResolve(false);
myStorage->refresh();
- updateMultiConstraints(myConstraints);
- // multi-constraints updated some parameters, need to store them
- if (myStorage->isNeedToResolve())
- resolveConstraints();
+//// updateMultiConstraints(myConstraints);
+//// // multi-constraints updated some parameters, need to store them
+//// if (myStorage->isNeedToResolve())
+//// resolveConstraints();
if (myPrevResult != STATUS_OK || myPrevResult == STATUS_UNKNOWN) {
getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue("");
myStorage->refresh();
}
removeTemporaryConstraints();
- myStorage->blockEvents(false);
myStorage->setNeedToResolve(false);
return aResolved;
}
// ============================================================================
-// Function: mergeGroups
-// Class: SketchSolver_Group
-// Purpose: append specified group to the current group
-// ============================================================================
-void SketchSolver_Group::mergeGroups(const SketchSolver_Group& theGroup)
-{
- // If specified group is empty, no need to merge
- if (theGroup.isEmpty())
- return;
-
- std::set<ObjectPtr> aConstraints;
- ConstraintConstraintMap::const_iterator aConstrIter = theGroup.myConstraints.begin();
- for (; aConstrIter != theGroup.myConstraints.end(); aConstrIter++)
- aConstraints.insert(aConstrIter->first);
-
- std::list<FeaturePtr> aSortedConstraints = selectApplicableFeatures(aConstraints);
- std::list<FeaturePtr>::iterator aSCIter = aSortedConstraints.begin();
- for (; aSCIter != aSortedConstraints.end(); ++aSCIter) {
- ConstraintPtr aConstr = std::dynamic_pointer_cast<SketchPlugin_Constraint>(*aSCIter);
- if (!aConstr)
- continue;
- changeConstraint(aConstr);
- }
-
- // merge previous states of groups => use the worst state,
- // so the group after rebuilt may discard error messages if exist
- if (theGroup.myPrevResult > myPrevResult)
- myPrevResult = theGroup.myPrevResult;
-}
-
-// ============================================================================
-// Function: splitGroup
-// Class: SketchSolver_Group
-// Purpose: divide the group into several subgroups
-// ============================================================================
-void SketchSolver_Group::splitGroup(std::list<SketchSolver_Group*>& theCuts)
-{
- // New storage will be used in trimmed way to store the list of constraint interacted together.
- StoragePtr aNewStorage = SketchSolver_Manager::instance()->builder()->createStorage(getId());
- // empty vector to avoid creation of solver's constraints
- std::list<ConstraintWrapperPtr> aDummyVec;
-
- // Obtain constraints, which should be separated
- std::list<ConstraintPtr> anUnusedConstraints;
- ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
- for ( ; aCIter != myConstraints.end(); aCIter++) {
- if (aNewStorage->isInteract(FeaturePtr(aCIter->first)))
- aNewStorage->addConstraint(aCIter->first, aDummyVec);
- else
- anUnusedConstraints.push_back(aCIter->first);
- }
-
- // Check the unused constraints once again,
- // because they may become interacted with new storage since adding constraints
- std::list<ConstraintPtr>::iterator aUnuseIt = anUnusedConstraints.begin();
- while (aUnuseIt != anUnusedConstraints.end()) {
- if (aNewStorage->isInteract(FeaturePtr(*aUnuseIt))) {
- aNewStorage->addConstraint(*aUnuseIt, aDummyVec);
- anUnusedConstraints.erase(aUnuseIt);
- aUnuseIt = anUnusedConstraints.begin();
- continue;
- }
- aUnuseIt++;
- }
-
- std::list<SketchSolver_Group*>::iterator aCutsIter;
- // Remove unused constraints
- for (aUnuseIt = anUnusedConstraints.begin(); aUnuseIt != anUnusedConstraints.end(); ++aUnuseIt)
- removeConstraint(*aUnuseIt);
-
- SketchSolver_Group* aBaseGroup;
- for (aUnuseIt = anUnusedConstraints.begin(); aUnuseIt != anUnusedConstraints.end(); ++aUnuseIt) {
- aBaseGroup = 0;
- aCutsIter = theCuts.begin();
- // Try to append constraint to the current group
- if (isInteract(*aUnuseIt)) {
- changeConstraint(*aUnuseIt);
- aBaseGroup = this;
- } else {
- // Try to append constraint to already existent group
- for (; aCutsIter != theCuts.end(); ++aCutsIter)
- if ((*aCutsIter)->isInteract(*aUnuseIt)) {
- (*aCutsIter)->changeConstraint(*aUnuseIt);
- break;
- }
- }
-
- if (aCutsIter == theCuts.end() && !aBaseGroup) {
- // Add new group
- SketchSolver_Group* aGroup = new SketchSolver_Group(mySketch);
- aGroup->changeConstraint(*aUnuseIt);
- theCuts.push_back(aGroup);
- } else {
- if (!aBaseGroup)
- aBaseGroup = *aCutsIter++;
- // Find other groups interacting with constraint
- for (; aCutsIter != theCuts.end(); ++aCutsIter)
- if ((*aCutsIter)->isInteract(*aUnuseIt)) {
- aBaseGroup->mergeGroups(**aCutsIter);
- std::list<SketchSolver_Group*>::iterator aRemoveIt = aCutsIter--;
- theCuts.erase(aRemoveIt);
- }
- }
- }
-}
-
-// ============================================================================
-// Function: isConsistent
+// Function: repairConsistency
// Class: SketchSolver_Group
// Purpose: search removed entities and constraints
// ============================================================================
-bool SketchSolver_Group::isConsistent()
+void SketchSolver_Group::repairConsistency()
{
- if (isEmpty()) // no one constraint is initialized yet
- return true;
-
- // Check the features and constraint is the storage are valid
- bool aResult = myStorage->isConsistent();
- if (aResult) {
- // additional check of consistency of the Fixed constraint,
- // because they are not added to the storage
- ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
- for (; aCIter != myConstraints.end(); ++aCIter)
- if (aCIter->first->getKind() == SketchPlugin_ConstraintRigid::ID() &&
- (!aCIter->first->data() || !aCIter->first->data()->isValid())) {
- aResult = false;
- break;
- }
- }
- if (!aResult) {
+ if (!myStorage->isConsistent()) {
// remove invalid constraints
std::set<ConstraintPtr> anInvalidConstraints;
ConstraintConstraintMap::iterator aCIter = myConstraints.begin();
std::set<ConstraintPtr>::const_iterator aRemoveIt = anInvalidConstraints.begin();
for (; aRemoveIt != anInvalidConstraints.end(); ++aRemoveIt)
removeConstraint(*aRemoveIt);
+
// remove invalid features
myStorage->removeInvalidEntities();
}
- return aResult;
}
// ============================================================================
// ============================================================================
void SketchSolver_Group::removeTemporaryConstraints()
{
- std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
- for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
- (*aTmpIt)->remove();
+ if (!myTempConstraints.empty()) {
+ std::dynamic_pointer_cast<PlaneGCSSolver_Solver>(
+ mySketchSolver)->removeConstraint(CID_MOVEMENT);
+
+ std::set<SolverConstraintPtr>::iterator aTmpIt = myTempConstraints.begin();
+ for (; aTmpIt != myTempConstraints.end(); ++aTmpIt)
+ (*aTmpIt)->remove();
+
+ myTempConstraints.clear();
+ }
- if (!myTempConstraints.empty())
- myStorage->verifyFixed();
myStorage->setNeedToResolve(false);
- myTempConstraints.clear();
}
// ============================================================================
for (; aCIter != myConstraints.end(); aCIter++)
if (aCIter->first == theConstraint) {
aCIter->second->remove(); // the constraint is not fully removed
- if (aCIter->first->getKind() == SketchPlugin_ConstraintCoincidence::ID())
- notifyCoincidenceChanged(aCIter->second);
break;
}
if (aCIter != myConstraints.end())
myConstraints.erase(aCIter);
- // empty group => clear storage
- if (myConstraints.empty()) {
- myStorage = StoragePtr();
- mySketchSolver = SolverPtr();
- updateWorkplane();
- }
}
// ============================================================================
myTempConstraints.insert(theConstraint);
}
-
// ============================================================================
-// Function: checkFeatureValidity
+// Function: blockEvents
// Class: SketchSolver_Group
-// Purpose: verifies is the feature valid
+// Purpose: block or unblock events from features in this group
// ============================================================================
-bool SketchSolver_Group::checkFeatureValidity(FeaturePtr theFeature)
-{
- if (!theFeature || !theFeature->data()->isValid())
- return true;
-
- SessionPtr aMgr = ModelAPI_Session::get();
- ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
- return aFactory->validate(theFeature);
-}
-
-
-
-
-// =========== Auxiliary functions ========================================
-static double featureToVal(FeaturePtr theFeature)
-{
- if (theFeature->getKind() == SketchPlugin_Sketch::ID())
- return 0.0; // sketch
- ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
- if (!aConstraint)
- return 1.0; // features (arc, circle, line, point)
-
- const std::string& anID = aConstraint->getKind();
- if (anID == SketchPlugin_ConstraintCoincidence::ID()) {
- AttributeRefAttrPtr anAttrA = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_A()));
- AttributeRefAttrPtr anAttrB = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aConstraint->attribute(SketchPlugin_Constraint::ENTITY_B()));
- if (anAttrA && anAttrB && (anAttrA->isObject() || anAttrB->isObject()))
- // point-on-line and point-on-circle should go before points coincidence constraint
- return 2.0;
- return 2.5;
- }
- if (anID == SketchPlugin_ConstraintDistance::ID() ||
- anID == SketchPlugin_ConstraintLength::ID() ||
- anID == SketchPlugin_ConstraintRadius::ID())
- return 3.0;
- if (anID == SketchPlugin_ConstraintAngle::ID())
- return 3.5;
- if (anID == SketchPlugin_ConstraintHorizontal::ID() ||
- anID == SketchPlugin_ConstraintVertical::ID() ||
- anID == SketchPlugin_ConstraintParallel::ID() ||
- anID == SketchPlugin_ConstraintPerpendicular::ID())
- return 4.0;
- if (anID == SketchPlugin_ConstraintEqual::ID())
- return 5.0;
- if (anID == SketchPlugin_ConstraintTangent::ID() ||
- anID == SketchPlugin_ConstraintMirror::ID())
- return 6.0;
- if (anID == SketchPlugin_ConstraintRigid::ID())
- return 0.5;
- if (anID == SketchPlugin_MultiRotation::ID() ||
- anID == SketchPlugin_MultiTranslation::ID())
- return 8.0;
-
- // all other constraints are placed between Equal and Tangent constraints
- return 5.5;
-}
-
-static bool isLess(FeaturePtr theFeature1, FeaturePtr theFeature2)
+void SketchSolver_Group::blockEvents(bool isBlocked)
{
- return featureToVal(theFeature1) < featureToVal(theFeature2);
-}
-
-std::list<FeaturePtr> SketchSolver_Group::
- selectApplicableFeatures(const std::set<ObjectPtr>& theObjects)
-{
- std::list<FeaturePtr> aResult;
- std::list<FeaturePtr>::iterator aResIt;
-
- std::set<ObjectPtr>::const_iterator anObjIter = theObjects.begin();
- for (; anObjIter != theObjects.end(); ++anObjIter) {
- // Operate sketch itself and SketchPlugin features only.
- // Also, the Fillet and Split need to be skipped,
- // because there are several separated constraints composing it.
- FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIter);
- if (!aFeature)
- continue;
- std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if ((aFeature->getKind() != SketchPlugin_Sketch::ID() && !aSketchFeature) ||
- aFeature->getKind() == SketchPlugin_ConstraintFillet::ID() ||
- aFeature->getKind() == SketchPlugin_ConstraintSplit::ID())
- continue;
-
- // Find the place where to insert a feature
- for (aResIt = aResult.begin(); aResIt != aResult.end(); ++aResIt)
- if (isLess(aFeature, *aResIt))
- break;
- aResult.insert(aResIt, aFeature);
- }
+ if (myIsEventsBlocked == isBlocked)
+ return;
- return aResult;
-}
+ // block/unblock events from the features in the storage
+ myStorage->blockEvents(isBlocked);
-void SketchSolver_Group::notifyCoincidenceChanged(SolverConstraintPtr theCoincidence)
-{
- const std::list<EntityWrapperPtr>& aCoincident = theCoincidence->attributes();
- EntityWrapperPtr anAttr1 = aCoincident.front();
- EntityWrapperPtr anAttr2 = aCoincident.back();
+ // block/unblock events from constraints
+ ConstraintConstraintMap::iterator aCIt = myConstraints.begin();
+ for (; aCIt != myConstraints.end(); ++aCIt)
+ aCIt->second->blockEvents(isBlocked);
- ConstraintConstraintMap::iterator anIt = myConstraints.begin();
- for (; anIt != myConstraints.end(); ++anIt)
- anIt->second->notifyCoincidenceChanged(anAttr1, anAttr2);
+ myIsEventsBlocked = isBlocked;
}
#ifndef SketchSolver_Group_H_
#define SketchSolver_Group_H_
-#include "SketchSolver.h"
#include <SketchSolver_Constraint.h>
#include <SketchSolver_Storage.h>
#include <SketchSolver_ISolver.h>
#include <SketchPlugin_Constraint.h>
-#include <ModelAPI_Feature.h>
#include <memory>
-#include <list>
#include <map>
-#include <set>
typedef std::map<ConstraintPtr, SolverConstraintPtr> ConstraintConstraintMap;
/** \class SketchSolver_Group
* \ingroup Plugins
- * \brief Keeps the group of constraints which based on the same entities
+ * \brief Keeps the group of constraints which placed in the same sketch
*/
class SketchSolver_Group
{
* Throws an exception if theWorkplane is not an object of SketchPlugin_Sketch type
* \remark Type of theSketch is not verified inside
*/
- SketchSolver_Group(std::shared_ptr<ModelAPI_CompositeFeature> theWorkplane);
+ SketchSolver_Group(const CompositeFeaturePtr& theWorkplane);
- ~SketchSolver_Group();
-
- /// \brief Returns group's unique identifier
- inline const GroupID& getId() const
- {
- return myID;
- }
-
- /// \brief Returns identifier of the workplane
- inline const EntityID& getWorkplaneId() const
- {
- return myWorkplaneID;
- }
+ virtual ~SketchSolver_Group();
/// \brief Returns true if the group has no constraints yet
inline bool isEmpty() const
return mySketch->data() && mySketch->data()->isValid();
}
- /// \brief Check the group has conflicting constraints
- inline bool isFailed() const
- {
- return !myConflictingConstraints.empty();
- }
-
/** \brief Adds or updates a constraint in the group
* \param[in] theConstraint constraint to be changed
* \return \c true if the constraint added or updated successfully
*/
bool moveFeature(FeaturePtr theFeature);
- /** \brief Verifies the feature attributes are used in this group
- * \param[in] theFeature constraint or any other object for verification of interaction
- * \return \c true if some of attributes are used in current group
- */
- bool isInteract(FeaturePtr theFeature) const;
-
- /** \brief Verifies the specified feature is equal to the base workplane for this group
- * \param[in] theWorkplane the feature to be compared with base workplane
- * \return \c true if workplanes are the same
- */
- bool isBaseWorkplane(CompositeFeaturePtr theWorkplane) const;
-
/// Returns the current workplane
- std::shared_ptr<ModelAPI_CompositeFeature> getWorkplane() const
+ inline const CompositeFeaturePtr& getWorkplane() const
{
return mySketch;
}
- /** \brief Update parameters of workplane. Should be called when Update event is coming.
- * \return \c true if workplane updated successfully,
- * \c false if workplane parameters are not consistent
- */
- bool updateWorkplane();
-
/** \brief Searches invalid features and constraints in the group and removes them
* \return \c false if the group several constraints were removed
*/
- bool isConsistent();
-
- /** \brief Add specified group to this one
- * \param[in] theGroup group of constraint to be added
- */
- void mergeGroups(const SketchSolver_Group& theGroup);
-
- /** \brief Cut from the group several subgroups, which are not connected to
- * the current one by any constraint
- * \param[out] theCuts enlarge this list by newly created groups
- */
- void splitGroup(std::list<SketchSolver_Group*>& theCuts);
+ void repairConsistency();
/** \brief Start solution procedure if necessary and update attributes of features
* \return \c false when no need to solve constraints
*/
bool resolveConstraints();
- /** \brief Collect all features applicable for the sketch
- * \param theObjects list of features
- * \return list of bolted and sorted features
- */
- static std::list<FeaturePtr> selectApplicableFeatures(const std::set<ObjectPtr>& theObjects);
+ /// \brief Block or unblock events sent by features in this group
+ void blockEvents(bool isBlocked);
-protected:
+private:
/** \brief Removes constraints from the group
* \param[in] theConstraint constraint to be removed
*/
void removeConstraint(ConstraintPtr theConstraint);
- /// \brief Remove all temporary constraint after computation finished
+ /// \brief Remove all temporary constraints after the computation finished
void removeTemporaryConstraints();
-private:
- /** \brief Creates a workplane from the sketch parameters
- * \param[in] theSketch parameters of workplane are the attributes of this sketch
- * \return \c true if success, \c false if workplane parameters are not consistent
- */
- bool addWorkplane(CompositeFeaturePtr theSketch);
-
/// \brief Append given constraint to the group of temporary constraints
void setTemporary(SolverConstraintPtr theConstraint);
- /// \brief Verifies is the feature valid
- bool checkFeatureValidity(FeaturePtr theFeature);
-
- /// \brief Notify all interested constraints that coincidence appears or removed
- /// \param[in] theCoincidence coincidence constraint
- void notifyCoincidenceChanged(SolverConstraintPtr theCoincidence);
-
private:
- GroupID myID; ///< Index of the group
- EntityID myWorkplaneID; ///< Index of workplane, the group is based on
- CompositeFeaturePtr mySketch; ///< Sketch is equivalent to workplane
+ CompositeFeaturePtr mySketch; ///< Sketch for this group
ConstraintConstraintMap myConstraints; ///< List of constraints
std::set<SolverConstraintPtr> myTempConstraints; ///< List of temporary constraints
- /// List of parametric constraints
- std::map<AttributePtr, SolverConstraintPtr> myParametricConstraints;
-
StoragePtr myStorage; ///< Container for the set of SolveSpace constraints and their entities
-
SolverPtr mySketchSolver; ///< Solver for set of equations obtained by constraints
/// Result of previous solution of the set of constraints
SketchSolver_SolveStatus myPrevResult;
std::set<ObjectPtr> myConflictingConstraints; ///< List of conflicting constraints
+
+ bool myIsEventsBlocked; ///< shows the events are blocked for this group
};
+typedef std::shared_ptr<SketchSolver_Group> SketchGroupPtr;
+
#endif
public:
virtual ~SketchSolver_IConstraintWrapper() {}
- /// \brief Return base feature
- const ConstraintPtr& baseConstraint() const
- { return myBaseConstraint; }
-
- /// \brief Return ID of current entity
- virtual ConstraintID id() const = 0;
-
- /// \brief Change group for the constraint
- virtual void setGroup(const GroupID& theGroup) = 0;
- /// \brief Return identifier of the group the constraint belongs to
- virtual GroupID group() const = 0;
+ /// \brief Return ID of current constraint
+ const ConstraintID& id() const
+ { return myID; }
+ /// \brief Change constraint ID
+ virtual void setId( const ConstraintID& theID) = 0;
/// \brief Return type of current entity
virtual SketchSolver_ConstraintType type() const = 0;
{ return myConstrained; }
/// \brief Assign numeric parameter of constraint
- virtual void setValue(const double& theValue)
- { myValue = theValue; }
+ virtual void setValue(const double& theValue) = 0;
/// \brief Return numeric parameter of constraint
- const double& value() const
- { return myValue; }
+ virtual double value() const = 0;
/// \brief Store a boolean flag for full value using
void setIsFullValue(const bool& theFullValue)
const bool& isFullValue() const
{ return myIsFullValue; }
- /// \brief Verify the feature is used in the constraint
- virtual bool isUsed(FeaturePtr theFeature) const = 0;
- /// \brief Verify the attribute is used in the constraint
- virtual bool isUsed(AttributePtr theAttribute) const = 0;
-
- /// \brief Compare current constraint with other
- virtual bool isEqual(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther) = 0;
-
- /// \brief Update values of parameters of this constraint by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IConstraintWrapper>& theOther) = 0;
-
protected:
- ConstraintPtr myBaseConstraint;
+ ConstraintID myID;
std::list<EntityWrapperPtr> myConstrained;
- double myValue;
bool myIsFullValue;
};
#define SketchSolver_IEntityWrapper_H_
#include <SketchSolver.h>
-#include <SketchSolver_IParameterWrapper.h>
#include <ModelAPI_Attribute.h>
#include <ModelAPI_Feature.h>
ENTITY_SCALAR,
ENTITY_ANGLE,
ENTITY_POINT,
- ENTITY_NORMAL,
ENTITY_LINE,
ENTITY_CIRCLE,
- ENTITY_ARC,
- ENTITY_SKETCH
+ ENTITY_ARC
};
/**
class SketchSolver_IEntityWrapper
{
public:
+ SketchSolver_IEntityWrapper() : myExternal(false) {}
virtual ~SketchSolver_IEntityWrapper() {}
- /// \brief Return base feature
- const FeaturePtr& baseFeature() const
- { return myBaseFeature; }
- /// \brief Return base attribute
- const AttributePtr& baseAttribute() const
- { return myBaseAttribute; }
-
- /// \brief Check the feature is basis for this wrapper
- bool isBase(FeaturePtr theFeature) const
- { return myBaseFeature && myBaseFeature == theFeature; }
- /// \brief Check the attribute is basis for this wrapper
- bool isBase(AttributePtr theAttribute) const
- { return myBaseAttribute && myBaseAttribute == theAttribute; }
-
- /// \brief Assign list of parameters for this entity
- void setParameters(const std::list<ParameterWrapperPtr>& theParams)
- { myParameters = theParams; }
- /// \brief Return list of parameters
- const std::list<ParameterWrapperPtr>& parameters() const
- { return myParameters; }
-
- /// \brief Assign list of sub-entities
- void setSubEntities(const std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >& theEntities)
- { mySubEntities = theEntities; }
- /// \brief Return list of sub-entities
- const std::list<std::shared_ptr<SketchSolver_IEntityWrapper> >& subEntities() const
- { return mySubEntities; }
-
- /// \brief Return ID of current entity
- virtual EntityID id() const = 0;
-
- /// \brief Change group for the entity
- virtual void setGroup(const GroupID& theGroup) = 0;
- /// \brief Return identifier of the group the entity belongs to
- virtual GroupID group() const = 0;
-
/// \brief Return type of current entity
virtual SketchSolver_EntityType type() const = 0;
- /// \brief Verify the feature is used in the entity
- virtual bool isUsed(FeaturePtr theFeature) const = 0;
- /// \brief Verify the attribute is used in the entity
- virtual bool isUsed(AttributePtr theAttribute) const = 0;
-
- /// \brief Compare current entity with other
- virtual bool isEqual(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther) = 0;
-
- /// \brief Update values of parameters of this entity by the parameters of given one
- /// \return \c true if some parameters change their values
- virtual bool update(const std::shared_ptr<SketchSolver_IEntityWrapper>& theOther) = 0;
-
-protected:
- FeaturePtr myBaseFeature;
- AttributePtr myBaseAttribute;
+ /// \brief Change flag indicating the entity cannot be changed in the solver
+ void setExternal(bool theExternal) { myExternal = theExternal; }
+ /// \brief Return the External flag
+ bool isExternal() const { return myExternal; }
- std::list<ParameterWrapperPtr> myParameters;
- std::list<std::shared_ptr<SketchSolver_IEntityWrapper> > mySubEntities;
+private:
+ bool myExternal;
};
typedef std::shared_ptr<SketchSolver_IEntityWrapper> EntityWrapperPtr;
+++ /dev/null
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-// File: SketchSolver_IParameterWrapper.h
-// Created: 1 Dec 2015
-// Author: Artem ZHIDKOV
-
-#ifndef SketchSolver_IParameterWrapper_H_
-#define SketchSolver_IParameterWrapper_H_
-
-#include <SketchSolver.h>
-
-#include <memory>
-
-/**
- * Wrapper providing operations with parameters regardless the solver.
- */
-class SketchSolver_IParameterWrapper
-{
-public:
- virtual ~SketchSolver_IParameterWrapper() {}
-
- /// \brief Return ID of current parameter
- virtual ParameterID id() const = 0;
-
- /// \brief Change group for the parameter
- virtual void setGroup(const GroupID& theGroup) = 0;
- /// \brief Return identifier of the group the parameter belongs to
- virtual GroupID group() const = 0;
-
- /// \brief Change value of parameter
- virtual void setValue(double theValue) = 0;
- /// \brief Return value of parameter
- virtual double value() const = 0;
-
- /// \brief Set or unset flag the parameter is given by expression
- void setIsParametric(bool isParametric)
- { myIsParametric = isParametric; }
- /// \brief Show the parameter is an expression
- bool isParametric() const
- { return myIsParametric; }
-
- /// \brief Compare current parameter with other
- virtual bool isEqual(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther) = 0;
-
- /// \brief Update value of parameter by the given one
- /// \return \c true if the value of parameter is changed
- virtual bool update(const std::shared_ptr<SketchSolver_IParameterWrapper>& theOther) = 0;
-
-protected:
- bool myIsParametric; ///< indicate the parameter is given by parametric expression
-};
-
-typedef std::shared_ptr<SketchSolver_IParameterWrapper> ParameterWrapperPtr;
-
-#endif
public:
virtual ~SketchSolver_ISolver() {}
- /// \brief Changes the ID of the group to solve
- void setGroup(const GroupID& theGroupID)
- { myGroup = theGroupID; }
-
/// \brief Set or unset the flag which allows to find all failed constraints
void calculateFailedConstraints(bool theSic)
{ myFindFaileds = theSic; }
virtual int dof() const = 0;
protected:
- GroupID myGroup; ///< ID of the group to be solved
bool myFindFaileds; ///< flag to find conflicting or inappropriate constraints
};
#include "SketchSolver_Error.h"
#include <Events_Loop.h>
-
-#include <GeomDataAPI_Point2D.h>
-
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeRefList.h>
-#include <ModelAPI_Data.h>
#include <ModelAPI_Events.h>
-#include <ModelAPI_Object.h>
#include <ModelAPI_ResultConstruction.h>
-#include <ModelAPI_Attribute.h>
-#include <ModelAPI_AttributeInteger.h>
-#include <ModelAPI_AttributeString.h>
-
-#include <SketchPlugin_Constraint.h>
-#include <SketchPlugin_ConstraintAngle.h>
-#include <SketchPlugin_ConstraintCoincidence.h>
-#include <SketchPlugin_ConstraintCollinear.h>
-#include <SketchPlugin_ConstraintDistance.h>
-#include <SketchPlugin_ConstraintEqual.h>
-#include <SketchPlugin_ConstraintHorizontal.h>
-#include <SketchPlugin_ConstraintLength.h>
-#include <SketchPlugin_ConstraintMiddle.h>
-#include <SketchPlugin_ConstraintMirror.h>
-#include <SketchPlugin_ConstraintParallel.h>
-#include <SketchPlugin_ConstraintPerpendicular.h>
-#include <SketchPlugin_ConstraintRadius.h>
-#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_ConstraintTangent.h>
-#include <SketchPlugin_ConstraintVertical.h>
-#include <SketchPlugin_MultiRotation.h>
-#include <SketchPlugin_MultiTranslation.h>
-
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Point.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
#include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Feature.h>
-#include <assert.h>
-#include <list>
-#include <set>
-#include <memory>
-#include <sstream>
+/// Global constraint manager object
+static SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
-static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+/// \brief Verifies is the feature valid
+static bool isFeatureValid(FeaturePtr theFeature)
+{
+ if (!theFeature || !theFeature->data() || !theFeature->data()->isValid())
+ return false;
-// Initialization of constraint manager self pointer
-SketchSolver_Manager* SketchSolver_Manager::mySelf = 0;
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
+ return aFactory->validate(theFeature);
+}
-/// Global constraint manager object
-SketchSolver_Manager* myManager = SketchSolver_Manager::instance();
// ========================================================
// ========================================================
SketchSolver_Manager* SketchSolver_Manager::instance()
{
+ static SketchSolver_Manager* mySelf = 0; // Self pointer to implement singleton functionality
if (!mySelf)
mySelf = new SketchSolver_Manager();
return mySelf;
// Register in event loop
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
- Events_Loop::loop()->registerListener(this, anUpdateEvent);
+ Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_DELETED));
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_MOVED));
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
- Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
+ ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_FAILED));
+ ////Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SOLVER_REPAIRED));
Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_SKETCH_PREPARED));
}
void SketchSolver_Manager::processEvent(
const std::shared_ptr<Events_Message>& theMessage)
{
+ static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
static const Events_ID aSketchPreparedEvent = Events_Loop::eventByName(EVENT_SKETCH_PREPARED);
// sketch is prepared for resolve: all the needed events
// are collected and must be processed by the solver
return;
}
- checkConflictingConstraints(theMessage);
-
if (myIsComputed)
return;
myIsComputed = true;
- // Shows that the message has at least one feature applicable for solver
- bool hasProperFeature = false;
-
if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)
|| theMessage->eventID() == anUpdateEvent
|| theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED)) {
bool isMovedEvt = theMessage->eventID()
== Events_Loop::loop()->eventByName(EVENT_OBJECT_MOVED);
- if (isMovedEvt) {
- std::set<ObjectPtr>::iterator aFeatIter;
- for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
- std::shared_ptr<SketchPlugin_Feature> aSFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (aSFeature && moveEntity(aSFeature)) {
- // Want to avoid recalculation of DoF too frequently.
- // So, set the flag when the feature is really moved.
- hasProperFeature = true;
- }
- }
- if (!hasProperFeature)
- // in this iteration it will compute nothing, so, no problem with recursion
- // it is important that solver flushes signal updated after processing move signal as there
- // is optimization that relies on this update, might be found by key "optimization"
- myIsComputed = false;
- } else {
- std::list<FeaturePtr> aSketchFeatures =
- SketchSolver_Group::selectApplicableFeatures(aFeatures);
- std::list<FeaturePtr>::iterator aFeatIter = aSketchFeatures.begin();
- for (; aFeatIter != aSketchFeatures.end(); ++aFeatIter) {
- if ((*aFeatIter)->getKind() == SketchPlugin_Sketch::ID()) {
- std::shared_ptr<ModelAPI_CompositeFeature> aSketch =
- std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIter);
- hasProperFeature = changeWorkplane(aSketch) || hasProperFeature;
- continue;
- }
- std::shared_ptr<SketchPlugin_Feature> aFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
- if (!aFeature)
- continue;
- hasProperFeature = changeFeature(aFeature) || hasProperFeature;
- }
+
+ // Shows that the message has at least one feature applicable for solver
+ bool hasProperFeature = false;
+
+ // update sketch features only
+ std::set<ObjectPtr>::iterator aFeatIter;
+ for (aFeatIter = aFeatures.begin(); aFeatIter != aFeatures.end(); aFeatIter++) {
+ std::shared_ptr<SketchPlugin_Feature> aFeature =
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aFeatIter);
+ if (!aFeature || aFeature->isMacro())
+ continue;
+
+ hasProperFeature = updateFeature(aFeature, isMovedEvt) || hasProperFeature;
+ }
+
+ if (isMovedEvt && !hasProperFeature) {
+ // in this iteration it will compute nothing, so, no problem with recursion
+ // it is important that solver flushes signal updated after processing move signal as there
+ // is optimization that relies on this update, might be found by key "optimization"
+ myIsComputed = false;
}
- bool needToUpdate = false;
// Solve the set of constraints
- if (hasProperFeature)
- needToUpdate = resolveConstraints();
+ bool needToUpdate = resolveConstraints();
// Features may be updated => now send events, but for all changed at once
if (isUpdateFlushed)
std::set<std::string>::const_iterator aFGrIter;
for (aFGrIter = aFeatureGroups.begin(); aFGrIter != aFeatureGroups.end(); aFGrIter++)
if (aFGrIter->compare(ModelAPI_ResultConstruction::group()) == 0 ||
- aFGrIter->compare(ModelAPI_Feature::group()) == 0)
+ aFGrIter->compare(ModelAPI_Feature::group()) == 0)
break;
if (aFGrIter != aFeatureGroups.end()) {
- hasProperFeature = true;
- std::list<SketchSolver_Group*> aGroupsToResolve;
- std::list<SketchSolver_Group*>::iterator aGroupIter = myGroups.begin();
- std::list<SketchSolver_Group*> aSeparatedGroups;
+ std::list<SketchGroupPtr>::iterator aGroupIter = myGroups.begin();
while (aGroupIter != myGroups.end()) {
if (!(*aGroupIter)->isWorkplaneValid()) { // the group should be removed
- delete *aGroupIter;
- std::list<SketchSolver_Group*>::iterator aRemoveIt = aGroupIter++;
+ std::list<SketchGroupPtr>::iterator aRemoveIt = aGroupIter++;
myGroups.erase(aRemoveIt);
continue;
}
- if (!(*aGroupIter)->isConsistent()) {
- // some constraints were removed, try to split the group
- (*aGroupIter)->splitGroup(aSeparatedGroups);
- if (!(*aGroupIter)->getWorkplane()->string(
- SketchPlugin_Sketch::SOLVER_ERROR())->value().empty() ||
- (*aGroupIter)->isFailed())
- aGroupsToResolve.push_back(*aGroupIter);
- }
- aGroupIter++;
- }
- if (aSeparatedGroups.size() > 0) {
- myGroups.insert(myGroups.end(), aSeparatedGroups.begin(), aSeparatedGroups.end());
- aGroupsToResolve.insert(aGroupsToResolve.end(),
- aSeparatedGroups.begin(), aSeparatedGroups.end());
- }
- if (!aGroupsToResolve.empty())
- resolveConstraints(aGroupsToResolve);
- }
- myIsComputed = false;
- }
-
- if (hasProperFeature)
- degreesOfFreedom();
-}
-
-void SketchSolver_Manager::
- checkConflictingConstraints(const std::shared_ptr<Events_Message>& theMessage)
-{
- if (theMessage->eventID() == Events_Loop::loop()->eventByName(EVENT_SOLVER_REPAIRED)) {
- std::shared_ptr<ModelAPI_SolverFailedMessage> aMessage =
- std::dynamic_pointer_cast<ModelAPI_SolverFailedMessage>(theMessage);
- std::set<ObjectPtr> aSentObjs = aMessage->objects();
- if (!aSentObjs.empty()) {
- // Obtain sketch where the constraints are placed.
- // It is enough to check only one constraint.
- CompositeFeaturePtr aSketch;
- FeaturePtr aConstraint = ModelAPI_Feature::feature(*aSentObjs.begin());
- std::list<SketchSolver_Group*>::const_iterator aGrIt = myGroups.begin();
- for (; aGrIt != myGroups.end(); ++aGrIt)
- if ((*aGrIt)->isInteract(aConstraint)) {
- aSketch = (*aGrIt)->getWorkplane();
- break;
- }
-
- // Search failed groups built on the same sketch
- if (aSketch) {
- for (aGrIt = myGroups.begin(); aGrIt != myGroups.end(); ++aGrIt) {
- SketchSolver_Group* aGroup = *aGrIt;
- if (aGroup->isBaseWorkplane(aSketch) && aGroup->isFailed() &&
- !aGroup->isInteract(aConstraint)) {
- // reset error message on the sketch
- aGroup->getWorkplane()->string(SketchPlugin_Sketch::SOLVER_ERROR())->setValue(
- SketchSolver_Error::CONSTRAINTS());
- break;
- }
- }
+ (*aGroupIter)->repairConsistency();
+ ++aGroupIter;
}
- }
- }
-}
-// ============================================================================
-// Function: changeWorkplane
-// Purpose: update workplane by given parameters of the sketch
-// ============================================================================
-bool SketchSolver_Manager::changeWorkplane(CompositeFeaturePtr theSketch)
-{
- bool aResult = true; // changed when a workplane wrongly updated
- bool isUpdated = false;
- // Try to update specified workplane in all groups
- std::list<SketchSolver_Group*>::iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if ((*aGroupIter)->isBaseWorkplane(theSketch)) {
- isUpdated = true;
- aResult = false;
+ resolveConstraints();
}
- // If the workplane is not updated, so this is a new workplane
- if (!isUpdated) {
- SketchSolver_Group* aNewGroup = new SketchSolver_Group(theSketch);
- // Verify that the group is created successfully
- if (!aNewGroup->isBaseWorkplane(theSketch) || !aNewGroup->isWorkplaneValid()) {
- delete aNewGroup;
- return false;
- }
- myGroups.push_back(aNewGroup);
+ myIsComputed = false;
}
- return aResult || isUpdated;
}
// ============================================================================
// Function: changeConstraintOrEntity
// Purpose: create/update the constraint or the feature and place it into appropriate group
// ============================================================================
-bool SketchSolver_Manager::changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature)
+bool SketchSolver_Manager::updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature,
+ bool theMoved)
{
- // Search the groups which this feature touches
- std::set<GroupID> aGroups;
- findGroups(theFeature, aGroups);
+ // Check feature validity and find a group to place it.
+ // If the feature is not valid, the returned group will be empty.
+ // This will protect to deal with wrong (not fully initialized) features.
+ SketchGroupPtr aGroup = findGroup(theFeature);
+ if (!aGroup)
+ return false;
+ aGroup->blockEvents(true);
std::shared_ptr<SketchPlugin_Constraint> aConstraint =
std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
- // Process the groups list
- if (aGroups.size() == 0) {
- // There are no groups applicable for this constraint => create new one
- // The group will be created only for constraints, not for features
- if (!aConstraint) return false;
- std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(aConstraint);
- if (!aWP)
- return false;
- SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
- if (!aGroup->changeConstraint(aConstraint)) {
- delete aGroup;
- return false;
- }
- myGroups.push_back(aGroup);
- return true;
- } else if (aGroups.size() == 1) { // Only one group => add feature into it
- GroupID aGroupId = *(aGroups.begin());
- std::list<SketchSolver_Group*>::iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if ((*aGroupIter)->getId() == aGroupId) {
- // If the group is empty, the feature is not added (the constraint only)
- if (!aConstraint && !(*aGroupIter)->isEmpty())
- return (*aGroupIter)->updateFeature(theFeature);
- return (*aGroupIter)->changeConstraint(aConstraint);
- }
- } else if (aGroups.size() > 1) {
- // Several groups applicable for this feature => need to merge them
- std::set<GroupID>::const_iterator aGroupsIter = aGroups.begin();
-
- // Search first group
- std::list<SketchSolver_Group*>::iterator aFirstGroupIter;
- for (aFirstGroupIter = myGroups.begin(); aFirstGroupIter != myGroups.end(); aFirstGroupIter++)
- if ((*aFirstGroupIter)->getId() == *aGroupsIter)
- break;
- if (aFirstGroupIter == myGroups.end())
- return false;
-
- // Append other groups to the first one
- std::list<SketchSolver_Group*>::iterator anOtherGroupIter = aFirstGroupIter;
- ++anOtherGroupIter;
- for (aGroupsIter++; aGroupsIter != aGroups.end(); aGroupsIter++) {
- for (; anOtherGroupIter != myGroups.end(); anOtherGroupIter++)
- if ((*anOtherGroupIter)->getId() == *aGroupsIter)
- break;
- if (anOtherGroupIter == myGroups.end()) { // Group disappears
- anOtherGroupIter = aFirstGroupIter;
- ++anOtherGroupIter;
- continue;
- }
-
- (*aFirstGroupIter)->mergeGroups(**anOtherGroupIter);
- std::list<SketchSolver_Group*>::iterator aRemoveIt = anOtherGroupIter++;
- delete *aRemoveIt;
- myGroups.erase(aRemoveIt);
- }
-
- if (aConstraint)
- (*aFirstGroupIter)->changeConstraint(aConstraint);
- else
- (*aFirstGroupIter)->updateFeature(theFeature);
- // groups are merged => need to resolve them
- return true;
- }
-
- // Something goes wrong
- return false;
-}
-
-// ============================================================================
-// Function: moveEntity
-// Purpose: update element moved on the sketch, which is used by constraints
-// ============================================================================
-bool SketchSolver_Manager::moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature)
-{
- bool isMoved = false;
- std::list<SketchSolver_Group*>::iterator aGroupIt = myGroups.begin();
- for (; aGroupIt != myGroups.end(); aGroupIt++)
- if (!(*aGroupIt)->isEmpty() && (*aGroupIt)->isInteract(theFeature))
- isMoved = (*aGroupIt)->moveFeature(theFeature) || isMoved;
-
- if (!isMoved && theFeature->getKind() == SketchPlugin_Arc::ID()) {
- // Workaround to move arc.
- // If the arc has not been constrained, we will push it into empty group and apply movement.
- bool hasEmptyGroup = false;
- for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); aGroupIt++)
- if ((*aGroupIt)->isEmpty()) {
- isMoved = (*aGroupIt)->moveFeature(theFeature) || isMoved;
- hasEmptyGroup = true;
- }
- // There is no empty group, create it explicitly
- if (!hasEmptyGroup) {
- // find sketch containing the arc
- CompositeFeaturePtr aWP;
- const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
- std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
- for (; aRefIt != aRefs.end(); ++aRefIt) {
- FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
- if (anOwner && anOwner->getKind() == SketchPlugin_Sketch::ID()) {
- aWP = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(anOwner);
- break;
- }
- }
- if (aWP) {
- SketchSolver_Group* aGroup = new SketchSolver_Group(aWP);
- isMoved = aGroup->moveFeature(theFeature) || isMoved;
- myGroups.push_back(aGroup);
- }
- }
- }
- return isMoved;
+ bool isOk = false;
+ if (aConstraint)
+ isOk = aGroup->changeConstraint(aConstraint);
+ else if (theMoved)
+ isOk = aGroup->moveFeature(theFeature);
+ else
+ isOk = aGroup->updateFeature(theFeature);
+ return isOk;
}
// ============================================================================
-// Function: findGroups
+// Function: findGroup
// Purpose: search groups of entities interacting with given feature
// ============================================================================
-void SketchSolver_Manager::findGroups(
- std::shared_ptr<SketchPlugin_Feature> theFeature,
- std::set<GroupID>& theGroupIDs) const
+SketchGroupPtr SketchSolver_Manager::findGroup(
+ std::shared_ptr<SketchPlugin_Feature> theFeature)
{
- std::shared_ptr<ModelAPI_CompositeFeature> aWP = findWorkplane(theFeature);
-
- SketchSolver_Group* anEmptyGroup = 0; // appropriate empty group for specified constraint
- std::list<SketchSolver_Group*>::const_iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++)
- if (aWP == (*aGroupIter)->getWorkplane() && (*aGroupIter)->isInteract(theFeature)) {
- if (!(*aGroupIter)->isEmpty())
- theGroupIDs.insert((*aGroupIter)->getId());
- else if (!anEmptyGroup)
- anEmptyGroup = *aGroupIter;
+ if (!isFeatureValid(theFeature))
+ return SketchGroupPtr(); // do not process wrong features
+
+ // Obtain sketch, containing the feature
+ CompositeFeaturePtr aSketch;
+ const std::set<AttributePtr>& aRefsList = theFeature->data()->refsToMe();
+ std::set<AttributePtr>::const_iterator aRefIt = aRefsList.begin();
+ for (; aRefIt != aRefsList.end(); ++aRefIt) {
+ FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
+ if (anOwner && anOwner->getKind() == SketchPlugin_Sketch::ID()) {
+ aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(anOwner);
+ break;
}
+ }
- // When only empty group is found, use it
- if (anEmptyGroup && theGroupIDs.empty())
- theGroupIDs.insert(anEmptyGroup->getId());
-}
+ if (!aSketch)
+ return SketchGroupPtr(); // not a sketch's feature
-// ============================================================================
-// Function: findWorkplane
-// Purpose: search workplane containing given feature
-// ============================================================================
-std::shared_ptr<ModelAPI_CompositeFeature> SketchSolver_Manager
-::findWorkplane(std::shared_ptr<SketchPlugin_Feature> theFeature) const
-{
- // Already verified workplanes
- std::set<std::shared_ptr<ModelAPI_CompositeFeature> > aVerified;
-
- std::list<SketchSolver_Group*>::const_iterator aGroupIter;
- for (aGroupIter = myGroups.begin(); aGroupIter != myGroups.end(); aGroupIter++) {
- std::shared_ptr<ModelAPI_CompositeFeature> aWP = (*aGroupIter)->getWorkplane();
- if (aVerified.find(aWP) != aVerified.end())
- continue;
-
- DataPtr aData = aWP->data();
- if (aData->isValid()) {
- std::shared_ptr<ModelAPI_AttributeRefList> aWPFeatures = std::dynamic_pointer_cast<
- ModelAPI_AttributeRefList>(aData->attribute(SketchPlugin_Sketch::FEATURES_ID()));
- std::list<ObjectPtr> aFeaturesList = aWPFeatures->list();
- std::list<ObjectPtr>::const_iterator anIter;
- for (anIter = aFeaturesList.begin(); anIter != aFeaturesList.end(); anIter++)
- if (*anIter == theFeature)
- return aWP; // workplane is found
- }
- aVerified.insert(aWP);
- }
+ std::list<SketchGroupPtr>::const_iterator aGroupIt;
+ for (aGroupIt = myGroups.begin(); aGroupIt != myGroups.end(); ++aGroupIt)
+ if ((*aGroupIt)->getWorkplane() == aSketch)
+ return *aGroupIt;
- return std::shared_ptr<ModelAPI_CompositeFeature>();
+ // group for the sketch does not created yet
+ SketchGroupPtr aNewGroup = SketchGroupPtr(new SketchSolver_Group(aSketch));
+ myGroups.push_back(aNewGroup);
+ return aNewGroup;
}
// ============================================================================
// Function: resolveConstraints
// Purpose: change entities according to available constraints
// ============================================================================
-bool SketchSolver_Manager::resolveConstraints(const std::list<SketchSolver_Group*>& theGroups)
+bool SketchSolver_Manager::resolveConstraints()
{
bool needToUpdate = false;
- const std::list<SketchSolver_Group*>& aGroupsToResolve = theGroups.empty() ?
- myGroups : theGroups;
- std::list<SketchSolver_Group*>::const_iterator aGroupIter = aGroupsToResolve.begin();
- for (; aGroupIter != aGroupsToResolve.end(); aGroupIter++)
+ std::list<SketchGroupPtr>::const_iterator aGroupIter = myGroups.begin();
+ for (; aGroupIter != myGroups.end(); ++aGroupIter) {
if ((*aGroupIter)->resolveConstraints())
needToUpdate = true;
- return needToUpdate;
-}
-
-
-// Obtain points and their copies for Mirror, Multi-Rotation and Multi-Translation constraints
-static void collectPointsAndCopies(FeaturePtr theConstraint,
- std::list<std::set<AttributePtr> >& thePoints)
-{
- typedef std::list<std::string> strlist;
- static strlist aPointAttributes(1, SketchPlugin_Point::COORD_ID());
- static strlist aLineAttributes;
- if (aLineAttributes.empty()) {
- aLineAttributes.push_back(SketchPlugin_Line::START_ID());
- aLineAttributes.push_back(SketchPlugin_Line::END_ID());
- };
- static strlist aCircleAttributes(1, SketchPlugin_Circle::CENTER_ID());
- static strlist anArcAttributes;
- if (anArcAttributes.empty()) {
- anArcAttributes.push_back(SketchPlugin_Arc::CENTER_ID());
- anArcAttributes.push_back(SketchPlugin_Arc::START_ID());
- anArcAttributes.push_back(SketchPlugin_Arc::END_ID());
- };
-
- static std::map<std::string, strlist> aFeatureAttributes;
- if (aFeatureAttributes.empty()) {
- aFeatureAttributes[SketchPlugin_Point::ID()] = aPointAttributes;
- aFeatureAttributes[SketchPlugin_Line::ID()] = aLineAttributes;
- aFeatureAttributes[SketchPlugin_Circle::ID()] = aCircleAttributes;
- aFeatureAttributes[SketchPlugin_Arc::ID()] = anArcAttributes;
- }
-
-
- std::set<AttributePtr> aPoints;
- if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID()) {
- AttributeRefListPtr aBaseRefList = theConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
- AttributeRefListPtr aMirrRefList = theConstraint->reflist(SketchPlugin_Constraint::ENTITY_C());
-
- std::list<ObjectPtr> aBaseList = aBaseRefList->list();
- std::list<ObjectPtr> aMirrList = aMirrRefList->list();
- std::list<ObjectPtr>::const_iterator aBIt, aMIt;
- for (aBIt = aBaseList.begin(), aMIt = aMirrList.begin();
- aBIt != aBaseList.end() && aMIt != aMirrList.end(); ++aBIt, ++aMIt) {
- FeaturePtr aBaseFeature = ModelAPI_Feature::feature(*aBIt);
- FeaturePtr aMirrFeature = ModelAPI_Feature::feature(*aMIt);
-
- strlist anAttrList = aFeatureAttributes[aBaseFeature->getKind()];
- strlist::iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt) {
- aPoints.clear();
- aPoints.insert(aBaseFeature->attribute(*anIt));
- aPoints.insert(aMirrFeature->attribute(*anIt));
- thePoints.push_back(aPoints);
- }
- }
- }
- else { // the "Multi" constraints
- std::string aNbObjName;
- if (theConstraint->getKind() == SketchPlugin_MultiRotation::ID())
- aNbObjName = SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID();
- else
- aNbObjName = SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID();
- int aNbCopies = theConstraint->integer(aNbObjName)->value();
-
- AttributeRefListPtr aRefList = theConstraint->reflist(SketchPlugin_Constraint::ENTITY_B());
- std::list<ObjectPtr> aFullList = aRefList->list();
- std::list<ObjectPtr>::const_iterator anObjIt = aFullList.begin();
- std::list<ObjectPtr>::const_iterator aCopyIt;
- while (anObjIt != aFullList.end()) {
- FeaturePtr aBaseFeature = ModelAPI_Feature::feature(*anObjIt);
- strlist anAttrList = aFeatureAttributes[aBaseFeature->getKind()];
- strlist::iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt) {
- aPoints.clear();
- aCopyIt = anObjIt;
- for (int i = 0; i < aNbCopies && aCopyIt != aFullList.end(); ++i, ++aCopyIt) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(*aCopyIt);
- aPoints.insert(aFeature->attribute(*anIt));
- }
- thePoints.push_back(aPoints);
- }
- anObjIt = aCopyIt;
- }
- }
-}
-
-
-// returns true if the feature is external
-static bool isExternal(const FeaturePtr& theFeature)
-{
- AttributeSelectionPtr anAttr = theFeature->selection(SketchPlugin_SketchEntity::EXTERNAL_ID());
- return anAttr && anAttr->context() && !anAttr->isInvalid();
-}
-
-// ============================================================================
-// Function: degreesOfFreedom
-// Purpose: calculate DoFs for each sketch
-// ============================================================================
-void SketchSolver_Manager::degreesOfFreedom()
-{
- static std::map<std::string, int> aDoFDelta; // indicates how many DoF adds or decreases a feature
- static bool isNeedInit = true;
- if (isNeedInit) {
- aDoFDelta[SketchPlugin_Point::ID()] = 2;
- aDoFDelta[SketchPlugin_Line::ID()] = 4;
- aDoFDelta[SketchPlugin_Circle::ID()] = 3;
- aDoFDelta[SketchPlugin_Arc::ID()] = 5;
-
- aDoFDelta[SketchPlugin_ConstraintAngle::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintCollinear::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintDistance::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintEqual::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintHorizontal::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintLength::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintParallel::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintPerpendicular::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintRadius::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintTangent::ID()] = -1;
- aDoFDelta[SketchPlugin_ConstraintVertical::ID()] = -1;
-
- isNeedInit = false;
- }
-
- std::map<CompositeFeaturePtr, int> aSketchDoF;
-
- std::list<SketchSolver_Group*>::const_iterator aGroupIt = myGroups.begin();
- for (; aGroupIt != myGroups.end(); ++aGroupIt) {
- CompositeFeaturePtr aSketch = (*aGroupIt)->getWorkplane();
- bool isSketchValid = aSketch->data() && aSketch->data()->isValid();
-
- if (isSketchValid) {
- std::shared_ptr<GeomDataAPI_Dir> aNormal =
- std::dynamic_pointer_cast<GeomDataAPI_Dir>(
- aSketch->data()->attribute(SketchPlugin_Sketch::NORM_ID()));
- isSketchValid = aNormal && aNormal->isInitialized();
- }
-
- if (!isSketchValid) {
- myDoF.erase(aSketch);
- continue;
- }
-
- // check conflicting constraints in the group
- if ((*aGroupIt)->isFailed())
- aSketchDoF[aSketch] = -1;
- // check the sketch is already processed
- if (aSketchDoF.find(aSketch) != aSketchDoF.end() || aSketchDoF[aSketch] < 0)
- continue;
-
- std::set<AttributePtr> aCoincidentPoints;
- std::set<AttributePtr> aFixedPoints;
- std::map<AttributePtr, std::set<FeaturePtr> > aPointOnLine;
- std::list<std::set<AttributePtr> > aPointsInMultiConstraints;
- int aDoF = 0;
- int aNbSubs = aSketch->numberOfSubs();
- for (int i = 0; i < aNbSubs; ++i) {
- FeaturePtr aFeature = aSketch->subFeature(i);
- // do not change DoF for external feature
- if (isExternal(aFeature))
- continue;
- // check DoF delta for invariant types
- std::map<std::string, int>::const_iterator aFound = aDoFDelta.find(aFeature->getKind());
- if (aFound != aDoFDelta.end()) {
- aDoF += aFound->second;
- continue;
- }
-
- // DoF delta in specific cases
- if (aFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID()) {
- AttributePtr aCoincPoint[2] = {AttributePtr(), AttributePtr()};
- FeaturePtr aCoincLine;
- for (int j = 0; j < 2; ++j) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j)));
- if (!aRefAttr)
- continue;
- if (!aRefAttr->isObject())
- aCoincPoint[j] = aRefAttr->attr();
- else {
- FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object());
- if (!anAttr)
- continue;
- if (anAttr->getKind() == SketchPlugin_Point::ID())
- aCoincPoint[j] = anAttr->attribute(SketchPlugin_Point::COORD_ID());
- else if (anAttr->getKind() == SketchPlugin_Line::ID())
- aCoincLine = anAttr;
- }
- }
- if (aCoincPoint[0] && aCoincPoint[1]) {
- bool isDoFDecreased = false;
- // point-point coincidence
- if (aCoincidentPoints.find(aCoincPoint[0]) == aCoincidentPoints.end() ||
- aCoincidentPoints.find(aCoincPoint[1]) == aCoincidentPoints.end()) {
- aDoF -= 2;
- isDoFDecreased = true;
- }
- // check the coincident point is used in "multi" constraints
- std::list<std::set<AttributePtr> >::const_iterator
- aPtIt = aPointsInMultiConstraints.begin();
- bool isFound[2] = {false, false};
- for (; aPtIt != aPointsInMultiConstraints.end(); ++aPtIt) {
- if ((!isFound[0] && (isFound[0] = (aPtIt->find(aCoincPoint[0]) != aPtIt->end())))
- || (!isFound[1] && (isFound[1] = (aPtIt->find(aCoincPoint[1]) != aPtIt->end()))))
- aCoincidentPoints.insert(aPtIt->begin(), aPtIt->end());
- if (isFound[0] && isFound[1])
- break;
- }
- // check both points are fixed => not need to decrease DoF
- bool isFixed[2] = { aFixedPoints.find(aCoincPoint[0]) != aFixedPoints.end(),
- aFixedPoints.find(aCoincPoint[1]) != aFixedPoints.end() };
- if (isFixed[0] && isFixed[1] && isDoFDecreased)
- aDoF += 2; // revert decrease of DoF
- else if (isFixed[0] && !isFixed[1])
- aFixedPoints.insert(aCoincPoint[1]);
- else if (!isFixed[0] && isFixed[1])
- aFixedPoints.insert(aCoincPoint[0]);
- } else {
- aDoF -= 1;
- if (aCoincPoint[0] && aCoincLine) {
- // if the point is already coincident to a line
- // (by middle point constraint), do not decrease DoF
- std::map<AttributePtr, std::set<FeaturePtr> >::iterator
- aPtFound = aPointOnLine.find(aCoincPoint[0]);
- if (aPtFound != aPointOnLine.end() &&
- aPtFound->second.find(aCoincLine) != aPtFound->second.end())
- aDoF += 1; // restore value decreased above
- else
- aPointOnLine[aCoincPoint[0]].insert(aCoincLine);
- }
- }
- for (int j = 0; j < 2; ++j)
- if (aCoincPoint[j])
- aCoincidentPoints.insert(aCoincPoint[j]);
- }
- else if (aFeature->getKind() == SketchPlugin_ConstraintMiddle::ID()) {
- AttributePtr aPoint;
- FeaturePtr aLine;
- for (int j = 0; j < 2; ++j) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j)));
- if (!aRefAttr)
- continue;
- if (aRefAttr->isObject())
- aLine = ModelAPI_Feature::feature(aRefAttr->object());
- else
- aPoint = aRefAttr->attr();
- }
- if (aPoint && aLine) {
- // if the point is already on the line, decrease 1 DoF, instead decrease 2 DoF
- std::map<AttributePtr, std::set<FeaturePtr> >::iterator
- aPtFound = aPointOnLine.find(aPoint);
- if (aPtFound != aPointOnLine.end() &&
- aPtFound->second.find(aLine) != aPtFound->second.end())
- aDoF -= 1;
- else {
- aDoF -= 2;
- aPointOnLine[aPoint].insert(aLine);
- }
- }
- }
- else if (aFeature->getKind() == SketchPlugin_ConstraintRigid::ID()) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aFeature->attribute(SketchPlugin_Constraint::ENTITY_A()));
- assert(aRefAttr);
- std::set<AttributePtr> aPoints;
- if (!aRefAttr->isObject()) {
- aDoF -= 2; // attribute is a point
- aPoints.insert(aRefAttr->attr());
- } else {
- FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object());
- if (anAttr) {
- if (isExternal(anAttr))
- continue; // feature is already fixed since it is external
- aDoF -= aDoFDelta[anAttr->getKind()];
- std::list<AttributePtr> aPtAttrs =
- anAttr->data()->attributes(GeomDataAPI_Point2D::typeId());
- aPoints.insert(aPtAttrs.begin(), aPtAttrs.end());
- }
- }
-
- // Check whether feature's points are already coincident with fixed points.
- // In this case we need to revert decrease of DoF for these points.
- // If the coordinates of fixed points are different, it will be processed by solver.
- for (int k = 0; k < i; ++k) {
- FeaturePtr aFeature = aSketch->subFeature(k);
- if (aFeature->getKind() != SketchPlugin_ConstraintCoincidence::ID())
- continue;
- AttributePtr aCoincPoint[2] = {AttributePtr(), AttributePtr()};
- for (int j = 0; j < 2; ++j) {
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
- aFeature->attribute(SketchPlugin_Constraint::ATTRIBUTE(j)));
- if (!aRefAttr)
- continue;
- if (!aRefAttr->isObject())
- aCoincPoint[j] = aRefAttr->attr();
- else {
- FeaturePtr anAttr = ModelAPI_Feature::feature(aRefAttr->object());
- if (anAttr && anAttr->getKind() == SketchPlugin_Point::ID())
- aCoincPoint[j] = anAttr->attribute(SketchPlugin_Point::COORD_ID());
- }
- }
- if (aCoincPoint[0] && aCoincPoint[1]) {
- if ((aFixedPoints.find(aCoincPoint[0]) != aFixedPoints.end() &&
- aPoints.find(aCoincPoint[1]) != aPoints.end()) ||
- (aFixedPoints.find(aCoincPoint[1]) != aFixedPoints.end() &&
- aPoints.find(aCoincPoint[0]) != aPoints.end()))
- aDoF += 2; // point already fixed
- }
- }
- // store fixed points
- aFixedPoints.insert(aPoints.begin(), aPoints.end());
- }
- else if (aFeature->getKind() == SketchPlugin_ConstraintMirror::ID() ||
- aFeature->getKind() == SketchPlugin_MultiRotation::ID() ||
- aFeature->getKind() == SketchPlugin_MultiTranslation::ID()) {
- int aNbCopies = 1;
- std::string anAttrName;
- if (aFeature->getKind() == SketchPlugin_ConstraintMirror::ID())
- anAttrName = SketchPlugin_Constraint::ENTITY_B();
- else {
- if (aFeature->getKind() == SketchPlugin_MultiRotation::ID())
- aNbCopies =
- aFeature->integer(SketchPlugin_MultiRotation::NUMBER_OF_OBJECTS_ID())->value() - 1;
- else if (aFeature->getKind() == SketchPlugin_MultiTranslation::ID())
- aNbCopies =
- aFeature->integer(SketchPlugin_MultiTranslation::NUMBER_OF_OBJECTS_ID())->value() - 1;
- anAttrName = SketchPlugin_Constraint::ENTITY_A();
- }
-
- AttributeRefListPtr aRefListOfShapes = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
- aFeature->attribute(anAttrName));
- std::list<ObjectPtr> anObjList = aRefListOfShapes->list();
- std::list<ObjectPtr>::const_iterator anObjIt = anObjList.begin();
- for (; anObjIt != anObjList.end(); ++anObjIt) {
- FeaturePtr aSub = ModelAPI_Feature::feature(*anObjIt);
- aDoF -= aDoFDelta[aSub->getKind()] * aNbCopies;
- }
- // collect points and their copies for correct calculation of DoF for coincident points
- collectPointsAndCopies(aFeature, aPointsInMultiConstraints);
- }
- }
-
- aSketchDoF[aSketch] = aDoF;
- }
-
- // Check the degrees of freedom are changed
- std::map<CompositeFeaturePtr, int>::const_iterator aDoFIt = aSketchDoF.begin();
- std::map<CompositeFeaturePtr, int>::iterator aFound;
- for (; aDoFIt != aSketchDoF.end(); ++aDoFIt) {
- if (aDoFIt->second < 0)
- continue; // conflicting constraints on the current sketch
- aFound = myDoF.find(aDoFIt->first);
- if (aFound != myDoF.end() && aFound->second == aDoFIt->second)
- continue; // nothing is changed
- myDoF[aDoFIt->first] = aDoFIt->second;
- // change attribute value
- std::ostringstream aStream;
- if (aDoFIt->second == 0)
- aStream << "Sketch fully fixed (DOF = " << aDoFIt->second << ")";
- else
- aStream << "DOF (degree of freedom) = " << aDoFIt->second;
- aDoFIt->first->data()->string(SketchPlugin_Sketch::SOLVER_DOF())->setValue(aStream.str());
+ (*aGroupIter)->blockEvents(false);
}
+ return needToUpdate;
}
bool SketchSolver_Manager::stopSendUpdate() const
{
+static const Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
// to avoid redisplay of each segment on update by solver one by one in the viewer
bool isUpdateFlushed = Events_Loop::loop()->isFlushed(anUpdateEvent);
if (isUpdateFlushed) {
void SketchSolver_Manager::allowSendUpdate() const
{
- Events_Loop::loop()->setFlushed(anUpdateEvent, true);
+ Events_Loop::loop()->setFlushed(Events_Loop::eventByName(EVENT_OBJECT_UPDATED), true);
}
/** \class SketchSolver_Manager
* \ingroup Plugins
* \brief Listens the changes of SketchPlugin features and transforms the Constraint
- * feature into the format understandable by SolveSpace library.
- *
- * Constraints created for SolveSpace library are divided into the groups.
- * The division order based on connectedness of the features by the constraints.
- * The groups may be fused or separated according to the new constraints.
+ * feature into the format understandable by sketch solver.
*
* \remark This is a singleton.
*/
/** \brief Main method to create constraint manager
* \return pointer to the singleton
*/
- SKETCHSOLVER_EXPORT static SketchSolver_Manager* instance();
+ static SketchSolver_Manager* instance();
/** \brief Implementation of Event Listener method
* \param[in] theMessage the data of the event
/// \brief Initialize builder for solver's data structure entities
/// \param theBuilder [in] solver's specific builder
- SKETCHSOLVER_EXPORT void setBuilder(BuilderPtr theBuilder);
+ void setBuilder(BuilderPtr theBuilder);
/// \brief Returns the builder specific for the solver
BuilderPtr builder();
/** \brief Adds or updates a constraint or an entity in the suitable group
* \param[in] theFeature sketch feature to be changed
+ * \param[in] theMoved \c true if the feature has been moved in the viewer
* \return \c true if the feature changed successfully
*/
- bool changeFeature(std::shared_ptr<SketchPlugin_Feature> theFeature);
+ bool updateFeature(std::shared_ptr<SketchPlugin_Feature> theFeature, bool theMoved = false);
/** \brief Removes a constraint from the manager
* \param[in] theConstraint constraint to be removed
*/
bool removeConstraint(std::shared_ptr<SketchPlugin_Constraint> theConstraint);
- /** \brief Adds or updates a workplane in the manager
- * \param[in] theSketch the feature to create or update workplane
- * \return \c true if the workplane changed successfully
- * \remark Type of theSketch is not verified inside
- */
- bool changeWorkplane(CompositeFeaturePtr theSketch);
-
- /** \brief Removes a workplane from the manager.
- * All groups based on such workplane will be removed too.
- * \param[in] theSketch the feature to be removed
- * \return \c true if the workplane removed successfully
- */
- bool removeWorkplane(std::shared_ptr<SketchPlugin_Sketch> theSketch);
-
- /** \brief Updates entity which is moved in GUI
- * \param[in] theFeature entity to be updated
- * \return \c true, if the entity has been moved
- */
- bool moveEntity(std::shared_ptr<SketchPlugin_Feature> theFeature);
-
/** \brief Goes through the list of groups and solve the constraints
- * \param[in] theGroups list of groups to be resolved (if empty list, all groups are resolved)
* \return \c true, if groups are resolved, and features should be updated
* (send the Update event)
*/
- bool resolveConstraints(const std::list<SketchSolver_Group*>& theGroups =
- std::list<SketchSolver_Group*>());
+ bool resolveConstraints();
private:
- /** \brief Searches list of groups which interact with specified feature
+ /** \brief Searches group which interact with specified feature
* \param[in] theFeature object to be found
- * \param[out] theGroups list of group indexes interacted with the feature
- */
- void findGroups(std::shared_ptr<SketchPlugin_Feature> theFeature,
- std::set<GroupID>& theGroupIDs) const;
-
- /** \brief Searches in the list of groups the workplane which contains specified feature
- * \param[in] theFeature object to be found
- * \return workplane containing the feature
+ * \return Pointer to corresponding group or NULL if the group cannot be created.
*/
- std::shared_ptr<ModelAPI_CompositeFeature> findWorkplane(
- std::shared_ptr<SketchPlugin_Feature> theFeature) const;
+ SketchGroupPtr findGroup(std::shared_ptr<SketchPlugin_Feature> theFeature);
/// \brief Stop sending the Update event until all features updated
/// \return \c true, if the last flushed event is Update
/// \brief Allow to send the Update event
void allowSendUpdate() const;
- /// \brief If the message shows that any group is repaired after conflicting,
- /// find other groups on the same sketch, which have conflicts.
- void checkConflictingConstraints(const std::shared_ptr<Events_Message>& theMessage);
-
- /// \brief Calculate DoF for each sketch and send messages if changed
- void degreesOfFreedom();
-
private:
- static SketchSolver_Manager* mySelf; ///< Self pointer to implement singleton functionality
- std::list<SketchSolver_Group*> myGroups; ///< Groups of constraints
- BuilderPtr myBuilder; ///< Builder for solver's entities
+ std::list<SketchGroupPtr> myGroups; ///< Groups of constraints
+ BuilderPtr myBuilder; ///< Builder for solver's entities
/// true if computation is performed and all "updates" are generated by this algo
/// and needs no recomputation
bool myIsComputed;
-
- std::map<CompositeFeaturePtr, int> myDoF; ///< Degree of freedom for corresponding sketch
};
#endif
// Author: Artem ZHIDKOV
#include <SketchSolver_Storage.h>
-#include <SketchSolver_Manager.h>
+#include <PlaneGCSSolver_UpdateCoincidence.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
-#include <GeomDataAPI_Point2D.h>
#include <ModelAPI_AttributeRefAttr.h>
#include <ModelAPI_AttributeRefList.h>
#include <SketchPlugin_Arc.h>
#include <SketchPlugin_ConstraintCoincidence.h>
#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintRigid.h>
-#include <SketchPlugin_Projection.h>
-/// \brief Verify two vectors of constraints are equal.
-/// Vectors differ by the order of elements are equal.
-static bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
- const std::list<ConstraintWrapperPtr>& theCVec2);
-
-/// \brief Convert result to feature or attribute
-static void resultToFeatureOrAttribute(const ObjectPtr& theResult,
- FeaturePtr& theFeature, AttributePtr& theAttribute);
-
-
-void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
- ConstraintWrapperPtr theSolverConstraint)
+SketchSolver_Storage::SketchSolver_Storage(SolverPtr theSolver)
+ : mySketchSolver(theSolver),
+ myNeedToResolve(false),
+ myEventsBlocked(false)
{
- if (theSolverConstraint) {
- std::list<ConstraintWrapperPtr> aConstrList(1, theSolverConstraint);
- addConstraint(theConstraint, aConstrList);
- } else
- addConstraint(theConstraint, std::list<ConstraintWrapperPtr>());
+ // create updaters (constraints processed at first)
+ UpdaterPtr aFeatureUpdater(new PlaneGCSSolver_UpdateFeature);
+ myUpdaters = UpdaterPtr(new PlaneGCSSolver_UpdateCoincidence(aFeatureUpdater));
}
-void SketchSolver_Storage::addConstraint(
- ConstraintPtr theConstraint,
- std::list<ConstraintWrapperPtr> theSolverConstraints)
+void SketchSolver_Storage::addConstraint(ConstraintPtr theConstraint,
+ ConstraintWrapperPtr theSolverConstraint)
{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
aFound = myConstraintMap.find(theConstraint);
- if (aFound == myConstraintMap.end() || !isEqual(aFound->second, theSolverConstraints))
+ if (aFound == myConstraintMap.end() || aFound->second != theSolverConstraint)
setNeedToResolve(true);
- if (theSolverConstraints.empty()) {
- // constraint links to the empty list, add its attributes linked to the empty entities
- std::list<AttributePtr> aRefAttrs =
- theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
- std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
- for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
- AttributeRefAttrPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
- if (aRef->isObject()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
- if (aFeature) addEntity(aFeature, EntityWrapperPtr());
- } else
- addEntity(aRef->attr(), EntityWrapperPtr());
- }
- std::list<AttributePtr> aRefLists =
- theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
- for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
- AttributeRefListPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
- std::list<ObjectPtr> anObj = aRef->list();
- std::list<ObjectPtr>::iterator anIt = anObj.begin();
- for (; anIt != anObj.end(); ++anIt) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
- if (aFeature) addEntity(aFeature, EntityWrapperPtr());
- }
- }
- }
- else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
- // Do not add point-point coincidence, because it is already made by setting
- // the same parameters for both points
- std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
- for (; aCIt != theSolverConstraints.end(); ++aCIt)
- update(*aCIt);
- }
-
- if (!theSolverConstraints.empty() || aFound == myConstraintMap.end())
- myConstraintMap[theConstraint] = theSolverConstraints;
+//// if (theSolverConstraints.empty()) {
+//// // constraint links to the empty list, add its attributes linked to the empty entities
+//// std::list<AttributePtr> aRefAttrs =
+//// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
+//// std::list<AttributePtr>::const_iterator anAttrIt = aRefAttrs.begin();
+//// for (; anAttrIt != aRefAttrs.end(); ++anAttrIt) {
+//// AttributeRefAttrPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIt);
+//// if (aRef->isObject()) {
+//// FeaturePtr aFeature = ModelAPI_Feature::feature(aRef->object());
+//// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
+//// } else
+//// addEntity(aRef->attr(), EntityWrapperPtr());
+//// }
+//// std::list<AttributePtr> aRefLists =
+//// theConstraint->data()->attributes(ModelAPI_AttributeRefList::typeId());
+//// for (anAttrIt = aRefLists.begin(); anAttrIt != aRefLists.end(); ++anAttrIt) {
+//// AttributeRefListPtr aRef = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIt);
+//// std::list<ObjectPtr> anObj = aRef->list();
+//// std::list<ObjectPtr>::iterator anIt = anObj.begin();
+//// for (; anIt != anObj.end(); ++anIt) {
+//// FeaturePtr aFeature = ModelAPI_Feature::feature(*anIt);
+//// if (aFeature) addEntity(aFeature, EntityWrapperPtr());
+//// }
+//// }
+//// }
+//// else if (theSolverConstraints.front()->type() != CONSTRAINT_PT_PT_COINCIDENT) {
+//// // Do not add point-point coincidence, because it is already made by setting
+//// // the same parameters for both points
+//// std::list<ConstraintWrapperPtr>::iterator aCIt = theSolverConstraints.begin();
+//// for (; aCIt != theSolverConstraints.end(); ++aCIt)
+//// update(*aCIt);
+//// }
+
+ if (!theSolverConstraint || aFound == myConstraintMap.end())
+ myConstraintMap[theConstraint] = theSolverConstraint;
// block events if necessary
if (myEventsBlocked && theConstraint && theConstraint->data() && theConstraint->data()->isValid())
theConstraint->data()->blockSendAttributeUpdated(myEventsBlocked);
void SketchSolver_Storage::addEntity(FeaturePtr theFeature,
EntityWrapperPtr theSolverEntity)
{
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
- if (aFound == myFeatureMap.end() || !aFound->second ||
- (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
- setNeedToResolve(true); // the entity is new or modified
-
- if (!theSolverEntity) {
+ if (theSolverEntity) {
+ myFeatureMap[theFeature] = theSolverEntity;
+ setNeedToResolve(true);
+ } else {
// feature links to the empty entity, add its attributes
std::list<AttributePtr> aPntAttrs = pointAttributes(theFeature);
std::list<AttributePtr>::const_iterator anAttrIt = aPntAttrs.begin();
for (; anAttrIt != aPntAttrs.end(); ++anAttrIt)
addEntity(*anAttrIt, EntityWrapperPtr());
- if (aFound == myFeatureMap.end())
- myFeatureMap[theFeature] = theSolverEntity;
- } else
myFeatureMap[theFeature] = theSolverEntity;
+ }
// block events if necessary
if (myEventsBlocked && theFeature->data() && theFeature->data()->isValid())
void SketchSolver_Storage::addEntity(AttributePtr theAttribute,
EntityWrapperPtr theSolverEntity)
{
- std::map<AttributePtr, EntityWrapperPtr>::const_iterator aFound =
- myAttributeMap.find(theAttribute);
- if (aFound == myAttributeMap.end() || !aFound->second ||
- (theSolverEntity && !aFound->second->isEqual(theSolverEntity)))
- setNeedToResolve(true); // the entity is new or modified
-
- if (theSolverEntity || aFound == myAttributeMap.end())
+ if (theSolverEntity) {
myAttributeMap[theAttribute] = theSolverEntity;
+ setNeedToResolve(true);
+ }
+
// block events if necessary
if (myEventsBlocked && theAttribute->owner() &&
theAttribute->owner()->data() && theAttribute->owner()->data()->isValid())
}
-static bool isCopyInMulti(std::shared_ptr<SketchPlugin_Feature> theFeature,
- const std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >& theConstraints)
-{
- if (!theFeature)
- return false;
- bool aResult = theFeature->isCopy();
- if (aResult) {
- const std::set<AttributePtr>& aRefs = theFeature->data()->refsToMe();
- for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
- aRefIt != aRefs.end() && aResult; ++aRefIt) {
- FeaturePtr anOwner = ModelAPI_Feature::feature((*aRefIt)->owner());
- if ((anOwner->getKind() == SketchPlugin_ConstraintMirror::ID() &&
- (*aRefIt)->id() == SketchPlugin_Constraint::ENTITY_C()) ||
- (anOwner->getKind() == SketchPlugin_Projection::ID()))
- aResult = false;
- }
- }
- return aResult;
-}
-
-bool SketchSolver_Storage::update(FeaturePtr theFeature, const GroupID& theGroup, bool theForce)
-{
- bool isUpdated = false;
- EntityWrapperPtr aRelated = entity(theFeature);
- if (!aRelated) { // Feature is not exist, create it
- std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(theFeature);
- bool isCopy = isCopyInMulti(aSketchFeature, myConstraintMap);
- // the feature is a copy in "Multi" constraint and does not used in other constraints
- if (!theForce && isCopy && myFeatureMap.find(theFeature) == myFeatureMap.end())
- return false;
-
- std::list<EntityWrapperPtr> aSubs;
- // Reserve the feature in the map of features (do not want to add several copies of it)
- myFeatureMap[theFeature] = aRelated;
- // Firstly, create/update its attributes
- std::list<AttributePtr> anAttrs = pointAttributes(theFeature);
- std::list<AttributePtr>::const_iterator anIt = anAttrs.begin();
- for (; anIt != anAttrs.end(); ++anIt) {
- if (!(*anIt)->isInitialized())
- return false;
- isUpdated = update(*anIt, theGroup, theForce) || isUpdated;
- aSubs.push_back(entity(*anIt));
- }
- // If the feature is a circle, add its radius as a sub
- if (theFeature->getKind() == SketchPlugin_Circle::ID()) {
- AttributePtr aRadius = theFeature->attribute(SketchPlugin_Circle::RADIUS_ID());
- isUpdated = update(aRadius, theGroup, theForce) || isUpdated;
- aSubs.push_back(entity(aRadius));
- }
- // If the feature if circle or arc, we need to add normal of the sketch to the list of subs
- if (theFeature->getKind() == SketchPlugin_Arc::ID() ||
- theFeature->getKind() == SketchPlugin_Circle::ID()) {
- EntityWrapperPtr aNormal = getNormal();
- if (aNormal) aSubs.push_back(aNormal);
- }
- // Secondly, convert feature
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
- // Check external feature
- if (aSketchFeature && (aSketchFeature->isExternal() || isCopy))
- aGroup = GID_OUTOFGROUP;
- aRelated = aBuilder->createFeature(theFeature, aSubs, aGroup);
- if (!aRelated)
- return false;
- addEntity(theFeature, aRelated);
- } else if (theGroup != GID_UNKNOWN)
- changeGroup(aRelated, theGroup);
- return update(aRelated) || isUpdated;
-}
-
-bool SketchSolver_Storage::update(AttributePtr theAttribute, const GroupID& theGroup, bool theForce)
-{
- if (!theAttribute->isInitialized())
- return false;
-
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject()) {
- FeaturePtr aFeature;
- resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
- if (aFeature)
- return update(aFeature, theGroup, theForce);
- } else {
- anAttribute = aRefAttr->attr();
- if (!anAttribute->isInitialized())
- return false;
- }
- }
-
- EntityWrapperPtr aRelated = entity(anAttribute);
- if (!aRelated) { // Attribute is not exist, create it
- // verify the attribute is a point of arc and add whole arc
- if (anAttribute->owner()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(anAttribute->owner());
- if (aFeature->getKind() == SketchPlugin_Arc::ID() &&
- myFeatureMap.find(aFeature) == myFeatureMap.end()) {
- // Additional checking that all attributes are initialized
- if (aFeature->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() &&
- aFeature->attribute(SketchPlugin_Arc::START_ID())->isInitialized() &&
- aFeature->attribute(SketchPlugin_Arc::END_ID())->isInitialized()) {
- return SketchSolver_Storage::update(aFeature, theGroup, theForce);
- } else {
- myFeatureMap[aFeature] = EntityWrapperPtr();
- myExistArc = true;
- }
- }
- }
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- GroupID aGroup = theGroup != GID_UNKNOWN ? theGroup : myGroupID;
- // Check attribute of external features
- std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(anAttribute->owner());
- if (aSketchFeature && (aSketchFeature->isExternal() ||
- isCopyInMulti(aSketchFeature, myConstraintMap)))
- aGroup = GID_OUTOFGROUP;
- aRelated = aBuilder->createAttribute(anAttribute, aGroup);
- if (!aRelated)
- return false;
- addEntity(anAttribute, aRelated);
- } else if (theGroup != GID_UNKNOWN)
- changeGroup(aRelated, theGroup);
- return update(aRelated);
-}
-
-
-const std::list<ConstraintWrapperPtr>& SketchSolver_Storage::constraint(
+const ConstraintWrapperPtr& SketchSolver_Storage::constraint(
const ConstraintPtr& theConstraint) const
{
- static std::list<ConstraintWrapperPtr> aDummy;
+ static ConstraintWrapperPtr aDummy;
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr>>::const_iterator
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
aFound = myConstraintMap.find(theConstraint);
if (aFound != myConstraintMap.end())
return aFound->second;
const EntityWrapperPtr& SketchSolver_Storage::entity(const FeaturePtr& theFeature) const
{
- static EntityWrapperPtr aDummy;
-
std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFound = myFeatureMap.find(theFeature);
if (aFound != myFeatureMap.end())
return aFound->second;
+
+ static EntityWrapperPtr aDummy;
return aDummy;
}
const EntityWrapperPtr& SketchSolver_Storage::entity(const AttributePtr& theAttribute) const
{
- static EntityWrapperPtr aDummy;
-
std::map<AttributePtr, EntityWrapperPtr>::const_iterator
aFound = myAttributeMap.find(theAttribute);
if (aFound != myAttributeMap.end())
AttributeRefAttrPtr aRefAttr =
std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
if (aRefAttr) {
+ AttributePtr anAttribute;
+
if (aRefAttr->isObject()) {
+ /// TODO: Check resultToFeatureOrAttribute() precisely. Create additional unit-test
FeaturePtr aFeature;
- AttributePtr anAttribute;
resultToFeatureOrAttribute(aRefAttr->object(), aFeature, anAttribute);
if (aFeature)
return entity(aFeature);
- else
- return entity(anAttribute);
} else
- return entity(aRefAttr->attr());
- }
- return aDummy;
-}
-
-bool SketchSolver_Storage::removeConstraint(ConstraintPtr theConstraint)
-{
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
- aFound = myConstraintMap.find(theConstraint);
- if (aFound == myConstraintMap.end())
- return true; // no constraint, already deleted
-
- // Remove constraint
- std::list<ConstraintWrapperPtr> aConstrList = aFound->second;
- myConstraintMap.erase(aFound);
- // Remove SolveSpace constraints
- bool isFullyRemoved = true;
- std::list<ConstraintWrapperPtr>::iterator anIt = aConstrList.begin();
- while (anIt != aConstrList.end()) {
- if (remove(*anIt)) {
- std::list<ConstraintWrapperPtr>::iterator aRemoveIt = anIt++;
- aConstrList.erase(aRemoveIt);
- } else {
- isFullyRemoved = false;
- ++anIt;
- }
- }
- return isFullyRemoved;
-}
-
-template <class ENT_TYPE>
-static bool isUsed(ConstraintWrapperPtr theConstraint, ENT_TYPE theEntity)
-{
- if (!theConstraint || !theEntity)
- return false;
- std::list<EntityWrapperPtr>::const_iterator anEntIt = theConstraint->entities().begin();
- for (; anEntIt != theConstraint->entities().end(); ++anEntIt)
- if ((*anEntIt)->isBase(theEntity))
- return true;
- return false;
-}
-
-static bool isUsed(EntityWrapperPtr theFeature, AttributePtr theSubEntity)
-{
- if (!theFeature || !theSubEntity)
- return false;
- std::list<EntityWrapperPtr>::const_iterator aSubIt = theFeature->subEntities().begin();
- for (; aSubIt != theFeature->subEntities().end(); ++aSubIt)
- if ((*aSubIt)->isBase(theSubEntity))
- return true;
- return false;
-}
-
-static bool isUsed(FeaturePtr theFeature, AttributePtr theAttribute)
-{
- if (!theFeature || !theAttribute)
- return false;
- std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt) {
- if (*anIt == theAttribute)
- return true;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
- if (aRefAttr && !aRefAttr->isObject() && aRefAttr->attr() == theAttribute)
- return true;
- }
- return false;
-}
-
-bool SketchSolver_Storage::isUsed(FeaturePtr theFeature) const
-{
- if (myFeatureMap.find(theFeature) != myFeatureMap.end())
- return true;
- // check constraints
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt)
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
- if (::isUsed(*aCWIt, theFeature))
- return true;
- // check attributes
- std::list<AttributePtr> anAttrList = pointAttributes(theFeature);
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt)
- if (isUsed(*anIt))
- return true;
- return false;
-}
-
-bool SketchSolver_Storage::isUsed(AttributePtr theAttribute) const
-{
- AttributePtr anAttribute = theAttribute;
- AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttribute);
- if (aRefAttr) {
- if (aRefAttr->isObject())
- return isUsed(ModelAPI_Feature::feature(aRefAttr->object()));
- else
anAttribute = aRefAttr->attr();
- }
-
- if (myAttributeMap.find(theAttribute) != myAttributeMap.end())
- return true;
- // check in constraints
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIt = myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt) {
- for (aCWIt = aCIt->second.begin(); aCWIt != aCIt->second.end(); ++aCWIt)
- if (::isUsed(*aCWIt, anAttribute))
- return true;
- // Additional check for the Fixed constraints, which have no wrapper associated.
- if (aCIt->first->getKind() == SketchPlugin_ConstraintRigid::ID() &&
- ::isUsed(FeaturePtr(aCIt->first), anAttribute))
- return true;
- }
- // check in features
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt)
- if (::isUsed(aFIt->second, anAttribute))
- return true;
- return false;
-}
-
-
-bool SketchSolver_Storage::removeEntity(FeaturePtr theFeature)
-{
- std::map<FeaturePtr, EntityWrapperPtr>::iterator aFound = myFeatureMap.find(theFeature);
- if (aFound == myFeatureMap.end())
- return true; // feature not found, nothing to delete
-
- EntityWrapperPtr anEntity = aFound->second;
- myFeatureMap.erase(aFound);
-
- // Check if the feature is not used by constraints, remove it
- if (!anEntity || (!isUsed(theFeature) && remove(anEntity)))
- return true;
-
- // feature is not removed, revert operation
- myFeatureMap[theFeature] = anEntity;
- update(anEntity);
- return false;
-}
-
-bool SketchSolver_Storage::removeEntity(AttributePtr theAttribute)
-{
- std::map<AttributePtr, EntityWrapperPtr>::iterator aFound = myAttributeMap.find(theAttribute);
- if (aFound == myAttributeMap.end())
- return true; // attribute not found, nothing to delete
-
- EntityWrapperPtr anEntity = aFound->second;
- myAttributeMap.erase(aFound);
-
- // Check if the attribute is not used by constraints and features, remove it
- if (!anEntity || (!isUsed(theAttribute) && remove(anEntity)))
- return true;
-
- // attribute is not removed, revert operation
- myAttributeMap[theAttribute] = anEntity;
- update(anEntity);
- return false;
-}
-
-// Merge groups containing given entities
-static void mergeGroups(std::list<std::set<EntityWrapperPtr> >& theGroups,
- const EntityWrapperPtr& theEntity1, const EntityWrapperPtr& theEntity2)
-{
- std::list<std::set<EntityWrapperPtr> >::iterator aFound1 = theGroups.end();
- std::list<std::set<EntityWrapperPtr> >::iterator aFound2 = theGroups.end();
- std::list<std::set<EntityWrapperPtr> >::iterator anIt = theGroups.begin();
- for (; anIt != theGroups.end() && (aFound1 == theGroups.end() || aFound2 == theGroups.end());
- ++anIt) {
- if (anIt->find(theEntity1) != anIt->end())
- aFound1 = anIt;
- if (anIt->find(theEntity2) != anIt->end())
- aFound2 = anIt;
- }
-
- if (aFound1 == aFound2 || aFound1 == theGroups.end() || aFound2 == theGroups.end())
- return; // nothing to merge
-
- aFound1->insert(aFound2->begin(), aFound2->end());
- theGroups.erase(aFound2);
-}
-
-bool SketchSolver_Storage::removeCoincidence(ConstraintWrapperPtr theConstraint)
-{
- std::list<EntityWrapperPtr> aPoints = theConstraint->entities();
- std::list<EntityWrapperPtr>::const_iterator aPIt;
-
- CoincidentPointsMap::iterator aPtPtIt = myCoincidentPoints.begin();
- for (; aPtPtIt != myCoincidentPoints.end(); ++aPtPtIt) {
- for (aPIt = aPoints.begin(); aPIt != aPoints.end(); ++aPIt)
- if (aPtPtIt->first == *aPIt ||
- aPtPtIt->second.find(*aPIt) != aPtPtIt->second.end())
- break;
- if (aPIt != aPoints.end())
- break;
- }
-
- if (aPtPtIt == myCoincidentPoints.end())
- return true; // already removed
-
- // Removing of coincidence may split this group of coincident point to several groups.
- // Find all of them and also the points which become alone.
- std::list< std::set<EntityWrapperPtr> > aCoincGroups;
- std::set<EntityWrapperPtr> aGroup;
- aGroup.insert(aPtPtIt->first);
- aCoincGroups.push_back(aGroup);
- std::set<EntityWrapperPtr>::const_iterator aTempIt = aPtPtIt->second.begin();
- for (; aTempIt != aPtPtIt->second.end(); ++aTempIt) {
- aGroup.clear();
- aGroup.insert(*aTempIt);
- aCoincGroups.push_back(aGroup);
- }
-
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::iterator
- aConstrIt = myConstraintMap.begin();
- for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
- if (aConstrIt->first->getKind() != SketchPlugin_ConstraintCoincidence::ID())
- continue;
-
- AttributeRefAttrPtr aRefAttr[2] = {
- aConstrIt->first->refattr(SketchPlugin_Constraint::ENTITY_A()),
- aConstrIt->first->refattr(SketchPlugin_Constraint::ENTITY_B())
- };
- AttributePtr anAttr[2];
- if (aConstrIt->first->data()->isValid()) {
- if (!aRefAttr[0] || !aRefAttr[1])
- continue;
-
- for (int i = 0; i < 2; ++i) {
- if (aRefAttr[i]->isObject()) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr[i]->object());
- if (!aFeature || (aFeature->getKind() != SketchPlugin_Point::ID() &&
- aFeature->getKind() != SketchPlugin_IntersectionPoint::ID()))
- continue;
- anAttr[i] = aFeature->attribute(SketchPlugin_Point::COORD_ID());
- } else
- anAttr[i] = aRefAttr[i]->attr();
- }
- } else {
- // obtain attributes from the constraint wrapper
- // if SketchPlugin_Constraint has invalid data (already removed)
- ConstraintWrapperPtr aWrapper = aConstrIt->second.front();
- anAttr[0] = aWrapper->entities().front()->baseAttribute();
- anAttr[1] = aWrapper->entities().back()->baseAttribute();
- }
-
- EntityWrapperPtr anEntities[2];
- for (int i = 0; i < 2; ++i) {
- std::map<AttributePtr, EntityWrapperPtr>::iterator
- aFound = myAttributeMap.find(anAttr[i]);
- if (aFound != myAttributeMap.end())
- anEntities[i] = aFound->second;
- }
- mergeGroups(aCoincGroups, anEntities[0], anEntities[1]);
- }
- // Collect alone points and build them new instances
- std::list<EntityWrapperPtr> aShutOffList;
- BuilderPtr aBuilder = SketchSolver_Manager::instance()->builder();
- std::map<EntityWrapperPtr, EntityWrapperPtr> aNotCoinc;
- std::list<std::set<EntityWrapperPtr> >::iterator aGroupIt = aCoincGroups.begin();
- while (aGroupIt != aCoincGroups.end()) {
- if (aGroupIt->size() == 1) {
- EntityWrapperPtr aPoint = *aGroupIt->begin();
- aShutOffList.push_back(aPoint);
- aNotCoinc[aPoint] =
- aBuilder->createAttribute(aPoint->baseAttribute(), myGroupID, mySketchID);
- std::list<std::set<EntityWrapperPtr> >::iterator aRemoveIt = aGroupIt++;
- aCoincGroups.erase(aRemoveIt);
- } else // point is not alone
- ++aGroupIt;
+ return entity(anAttribute);
}
- if (aNotCoinc.empty() && aCoincGroups.size() == 1)
- return false;
-
- // Find all features and constraints uses non-coincident points
- replaceEntities(aNotCoinc);
-
- // Remove not coincident points and points in separated groups
- if (!aCoincGroups.empty()) {
- aGroupIt = aCoincGroups.begin();
- for (++aGroupIt; aGroupIt != aCoincGroups.end(); ++aGroupIt)
- aShutOffList.insert(aShutOffList.end(), aGroupIt->begin(), aGroupIt->end());
- }
- std::list<EntityWrapperPtr>::iterator aNotCIt = aShutOffList.begin();
- for (; aNotCIt != aShutOffList.end(); ++aNotCIt) {
- if (aPtPtIt->second.size() <= 1) {
- myCoincidentPoints.erase(aPtPtIt);
- break;
- }
- if (aPtPtIt->first == *aNotCIt) {
- std::set<EntityWrapperPtr> aSlaves = aPtPtIt->second;
- EntityWrapperPtr aNewMaster = *aSlaves.begin();
- aSlaves.erase(aSlaves.begin());
- myCoincidentPoints.erase(aPtPtIt);
- myCoincidentPoints[aNewMaster] = aSlaves;
- aPtPtIt = myCoincidentPoints.find(aNewMaster);
- } else
- aPtPtIt->second.erase(*aNotCIt);
- }
-
- // Create additional groups of coincident points
- aGroupIt = aCoincGroups.begin();
- if (!aCoincGroups.empty())
- ++aGroupIt;
- for (; aGroupIt != aCoincGroups.end(); ++aGroupIt) {
- aNotCoinc.clear();
- std::set<EntityWrapperPtr>::iterator anEntIt = aGroupIt->begin();
- for (; anEntIt != aGroupIt->end(); ++anEntIt) {
- aNotCoinc[*anEntIt] =
- aBuilder->createAttribute((*anEntIt)->baseAttribute(), myGroupID, mySketchID);
- }
- // replace points by newly created
- replaceEntities(aNotCoinc);
- // set new group of coincident points
- EntityWrapperPtr aMasterEnt = aNotCoinc.begin()->second;
- std::map<EntityWrapperPtr, EntityWrapperPtr>::iterator aNCIt = aNotCoinc.begin();
- for (++aNCIt; aNCIt != aNotCoinc.end(); ++aNCIt)
- addCoincidentPoints(aMasterEnt, aNCIt->second);
- }
-
- return true;
+ static EntityWrapperPtr aDummy;
+ return aDummy;
}
-void SketchSolver_Storage::replaceEntities(const std::map<EntityWrapperPtr,
- EntityWrapperPtr>& theChange)
-{
- std::set<EntityWrapperPtr> anUpdFeatures;
- std::map<EntityWrapperPtr, EntityWrapperPtr>::const_iterator aSubIt;
- std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt) {
- if (!aFIt->second)
- continue; // avoid not completed arcs
- for (aSubIt = theChange.begin(); aSubIt != theChange.end(); ++aSubIt) {
- if (!aSubIt->second || !::isUsed(aFIt->first, aSubIt->first->baseAttribute()))
- continue;
- std::list<EntityWrapperPtr> aSubs = aFIt->second->subEntities();
- std::list<EntityWrapperPtr>::iterator aSIt = aSubs.begin();
- bool isUpd = false;
- for (; aSIt != aSubs.end(); ++aSIt)
- if (*aSIt == aSubIt->first) {
- (*aSIt)->update(aSubIt->second);
- (*aSIt)->setGroup(aFIt->second->group());
- isUpd = true;
- }
- if (isUpd) {
- aFIt->second->setSubEntities(aSubs);
- anUpdFeatures.insert(aFIt->second);
- }
- }
- }
- // update features
- std::set<EntityWrapperPtr>::iterator anUpdIt = anUpdFeatures.begin();
- for (; anUpdIt != anUpdFeatures.end(); ++anUpdIt)
- update(EntityWrapperPtr(*anUpdIt));
-}
-bool SketchSolver_Storage::remove(ConstraintWrapperPtr theConstraint)
+void SketchSolver_Storage::removeFeature(FeaturePtr theFeature)
{
- bool isFullyRemoved = true;
- std::list<EntityWrapperPtr>::const_iterator anIt = theConstraint->entities().begin();
- for (; anIt != theConstraint->entities().end(); ++anIt) {
- FeaturePtr aBaseFeature = (*anIt)->baseFeature();
- if (aBaseFeature)
- isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
- else
- isFullyRemoved =
- SketchSolver_Storage::removeEntity((*anIt)->baseAttribute()) && isFullyRemoved;
- }
- return isFullyRemoved;
+ myFeatureMap.erase(theFeature);
}
-bool SketchSolver_Storage::remove(EntityWrapperPtr theEntity)
+void SketchSolver_Storage::removeAttribute(AttributePtr theAttribute)
{
- bool isFullyRemoved = true;
- std::list<EntityWrapperPtr>::const_iterator anEntIt = theEntity->subEntities().begin();
- for (; anEntIt != theEntity->subEntities().end(); ++anEntIt) {
- FeaturePtr aBaseFeature = (*anEntIt)->baseFeature();
- if (aBaseFeature)
- isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseFeature) && isFullyRemoved;
- else {
- AttributePtr aBaseAttr = (*anEntIt)->baseAttribute();
- if (aBaseAttr)
- isFullyRemoved = SketchSolver_Storage::removeEntity(aBaseAttr) && isFullyRemoved;
- else
- remove(*anEntIt);
- }
- }
-
- std::list<ParameterWrapperPtr>::const_iterator aParIt = theEntity->parameters().begin();
- for (; aParIt != theEntity->parameters().end(); ++aParIt)
- isFullyRemoved = remove(*aParIt) && isFullyRemoved;
- return isFullyRemoved;
+ myAttributeMap.erase(theAttribute);
}
-bool SketchSolver_Storage::isInteract(const FeaturePtr& theFeature) const
-{
- if (!theFeature)
- return false;
- if (myConstraintMap.empty())
- return true; // empty storage interacts with each feature
-
- ConstraintPtr aConstraint = std::dynamic_pointer_cast<SketchPlugin_Constraint>(theFeature);
- if (aConstraint) {
- if (myConstraintMap.find(aConstraint) != myConstraintMap.end())
- return true;
- } else if (myFeatureMap.find(theFeature) != myFeatureMap.end())
- return true;
-
- std::list<AttributePtr> anAttrList = theFeature->data()->attributes(std::string());
- std::list<AttributePtr>::const_iterator anIt = anAttrList.begin();
- for (; anIt != anAttrList.end(); ++anIt)
- if (isInteract(*anIt))
- return true;
-
- return false;
-}
-
-bool SketchSolver_Storage::isInteract(const AttributePtr& theAttribute) const
-{
- if (!theAttribute)
- return false;
-
- AttributeRefListPtr aRefList =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(theAttribute);
- if (aRefList) {
- std::list<ObjectPtr> anObjects = aRefList->list();
- std::list<ObjectPtr>::iterator anObjIt = anObjects.begin();
- for (; anObjIt != anObjects.end(); ++anObjIt) {
- FeaturePtr aFeature = ModelAPI_Feature::feature(*anObjIt);
- if (isInteract(aFeature))
- return true;
- }
- return false;
- }
-
- AttributeRefAttrPtr aRefAttr =
- std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
- if (!aRefAttr)
- return myAttributeMap.find(theAttribute) != myAttributeMap.end();
- if (!aRefAttr->isObject())
- return myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end();
-
- FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
- return isInteract(aFeature);
-}
-
bool SketchSolver_Storage::isConsistent() const
{
// Check the constraints are valid
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
aCIter = myConstraintMap.begin();
for (; aCIter != myConstraintMap.end(); ++aCIter)
if (!aCIter->first->data() || !aCIter->first->data()->isValid())
return true;
}
-bool SketchSolver_Storage::isFixed(EntityWrapperPtr theEntity) const
-{
- if (theEntity->group() != myGroupID)
- return true;
- // no need additional checking for entities differ than point
- if (theEntity->type() != ENTITY_POINT)
- return false;
-
- CoincidentPointsMap::const_iterator anIt = myCoincidentPoints.begin();
- for (; anIt != myCoincidentPoints.end(); ++anIt)
- if (anIt->first == theEntity || anIt->second.find(theEntity) != anIt->second.end()) {
- if (anIt->first->group() != myGroupID)
- return true;
- std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
- for (; anEntIt != anIt->second.end(); ++anEntIt)
- if ((*anEntIt)->group() != myGroupID)
- return true;
- }
-
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator aCIt =
- myConstraintMap.begin();
- std::list<ConstraintWrapperPtr>::const_iterator aCWIt;
- for (; aCIt != myConstraintMap.end(); ++aCIt) {
- if (aCIt->second.empty())
- continue;
- aCWIt = aCIt->second.begin();
- if ((*aCWIt)->type() != CONSTRAINT_FIXED)
- continue;
- for (; aCWIt != aCIt->second.end(); ++aCIt)
- if ((theEntity->baseAttribute() && (*aCWIt)->isUsed(theEntity->baseAttribute())) ||
- (theEntity->baseFeature() && (*aCWIt)->isUsed(theEntity->baseFeature())))
- return true;
- }
-
- return false;
-}
-
-void SketchSolver_Storage::removeInvalidEntities()
-{
- // Remove invalid constraints
- std::list<ConstraintPtr> anInvalidConstraints;
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIter = myConstraintMap.begin();
- for (; aCIter != myConstraintMap.end(); ++aCIter)
- if (!aCIter->first->data() || !aCIter->first->data()->isValid())
- anInvalidConstraints.push_back(aCIter->first);
- std::list<ConstraintPtr>::const_iterator anInvCIt = anInvalidConstraints.begin();
- for (; anInvCIt != anInvalidConstraints.end(); ++anInvCIt)
- removeConstraint(*anInvCIt);
- // Remove invalid features
- std::list<FeaturePtr> anInvalidFeatures;
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
- for (; aFIter != myFeatureMap.end(); aFIter++)
- if (!aFIter->first->data() || !aFIter->first->data()->isValid())
- anInvalidFeatures.push_back(aFIter->first);
- std::list<FeaturePtr>::const_iterator anInvFIt = anInvalidFeatures.begin();
- for (; anInvFIt != anInvalidFeatures.end(); ++anInvFIt)
- removeEntity(*anInvFIt);
-}
-
-EntityWrapperPtr SketchSolver_Storage::getNormal() const
-{
- EntityWrapperPtr aSketch = sketch();
- if (!aSketch)
- return aSketch;
-
- // Find normal entity
- const std::list<EntityWrapperPtr>& aSketchSubs = aSketch->subEntities();
- std::list<EntityWrapperPtr>::const_iterator aSIt = aSketchSubs.begin();
- for (; aSIt != aSketchSubs.end(); ++aSIt)
- if ((*aSIt)->type() == ENTITY_NORMAL)
- return *aSIt;
- return EntityWrapperPtr();
-}
-
-const EntityWrapperPtr& SketchSolver_Storage::sketch() const
-{
- static EntityWrapperPtr aDummySketch;
-
- std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt)
- if (aFIt->second && aFIt->second->type() == ENTITY_SKETCH)
- break;
- if (aFIt == myFeatureMap.end())
- return aDummySketch;
- return aFIt->second;
-}
-
-void SketchSolver_Storage::setSketch(const EntityWrapperPtr& theSketch)
-{
- if (sketch())
- return;
- addEntity(FeaturePtr(), theSketch);
-}
-
-void SketchSolver_Storage::processArcs()
-{
- myExistArc = false;
- std::map<FeaturePtr, EntityWrapperPtr>::iterator aFIt = myFeatureMap.begin();
- for (; aFIt != myFeatureMap.end(); ++aFIt)
- if (!aFIt->second && aFIt->first->getKind() == SketchPlugin_Arc::ID()) {
- // Additional checking the attributes are initialized
- if (aFIt->first->attribute(SketchPlugin_Arc::CENTER_ID())->isInitialized() &&
- aFIt->first->attribute(SketchPlugin_Arc::START_ID())->isInitialized() &&
- aFIt->first->attribute(SketchPlugin_Arc::END_ID())->isInitialized())
- update(aFIt->first);
- else
- myExistArc = true;
- }
-}
-
void SketchSolver_Storage::blockEvents(bool isBlocked)
{
- if (isBlocked == myEventsBlocked)
- return;
-
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
- aCIter = myConstraintMap.begin();
- for (; aCIter != myConstraintMap.end(); aCIter++)
- if (aCIter->first->data() && aCIter->first->data()->isValid())
- aCIter->first->data()->blockSendAttributeUpdated(isBlocked);
-
std::map<FeaturePtr, EntityWrapperPtr>::const_iterator aFIter = myFeatureMap.begin();
for (; aFIter != myFeatureMap.end(); aFIter++)
if (aFIter->first->data() && aFIter->first->data()->isValid())
if (anAtIter->first->owner() && anAtIter->first->owner()->data() &&
anAtIter->first->owner()->data()->isValid())
anAtIter->first->owner()->data()->blockSendAttributeUpdated(isBlocked);
+
myEventsBlocked = isBlocked;
}
std::set<ObjectPtr> SketchSolver_Storage::getConflictingConstraints(SolverPtr theSolver) const
{
std::set<ObjectPtr> aConflicting;
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> >::const_iterator
+ std::map<ConstraintPtr, ConstraintWrapperPtr>::const_iterator
aConstrIt = myConstraintMap.begin();
for (; aConstrIt != myConstraintMap.end(); ++aConstrIt) {
- std::list<ConstraintWrapperPtr>::const_iterator anIt = aConstrIt->second.begin();
- for (; anIt != aConstrIt->second.end(); ++anIt)
- if (theSolver->isConflicting((*anIt)->id())) {
- aConflicting.insert(aConstrIt->first);
- break;
- }
+ if (theSolver->isConflicting(aConstrIt->second->id())) {
+ aConflicting.insert(aConstrIt->first);
+ break;
+ }
}
return aConflicting;
}
+void SketchSolver_Storage::subscribeUpdates(
+ SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const
+{
+ myUpdaters->attach(theSubscriber, theGroup);
+}
+void SketchSolver_Storage::unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const
+{
+ myUpdaters->detach(theSubscriber);
+}
-
-
-// ============== Auxiliary functions ====================================
-bool isEqual(const std::list<ConstraintWrapperPtr>& theCVec1,
- const std::list<ConstraintWrapperPtr>& theCVec2)
+void SketchSolver_Storage::notify(const FeaturePtr & theFeature) const
{
- if (theCVec1.size() != theCVec2.size())
- return false;
-
- std::list<bool> aChecked(theCVec2.size(), false);
- std::list<ConstraintWrapperPtr>::const_iterator anIt1 = theCVec1.begin();
- for (; anIt1 != theCVec1.end(); ++anIt1) {
- std::list<ConstraintWrapperPtr>::const_iterator anIt2 = theCVec2.begin();
- std::list<bool>::iterator aCheckIt = aChecked.begin();
- while (aCheckIt != aChecked.end() && *aCheckIt) {
- ++aCheckIt;
- ++anIt2;
- }
- for (; anIt2 != theCVec2.end(); ++anIt2, ++aCheckIt)
- if (!(*aCheckIt) && (*anIt1)->isEqual(*anIt2)) {
- *aCheckIt = true;
- break;
- }
- // the same constraint is not found
- if (anIt2 == theCVec2.end())
- return false;
- }
- return true;
+ myUpdaters->update(theFeature);
}
-void resultToFeatureOrAttribute(const ObjectPtr& theResult,
+void SketchSolver_Storage::resultToFeatureOrAttribute(const ObjectPtr& theResult,
FeaturePtr& theFeature, AttributePtr& theAttribute)
{
FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
+ if (!aFeature)
+ return;
+
// if the feature has several results, we choose which one is referred
const std::list<ResultPtr>& aResults = aFeature->results();
if (aResults.size() > 1 && theResult != aFeature->lastResult()) {
#include <SketchSolver.h>
#include <SketchSolver_IConstraintWrapper.h>
#include <SketchSolver_IEntityWrapper.h>
-#include <SketchSolver_IParameterWrapper.h>
#include <SketchSolver_ISolver.h>
+#include <PlaneGCSSolver_UpdateFeature.h>
+
#include <ModelAPI_Attribute.h>
#include <ModelAPI_AttributeDouble.h>
#include <ModelAPI_Feature.h>
class SketchSolver_Storage
{
private:
- SketchSolver_Storage();
SketchSolver_Storage(const SketchSolver_Storage&);
SketchSolver_Storage& operator=(const SketchSolver_Storage&);
public:
- SketchSolver_Storage(const GroupID& theGroup)
- : myGroupID(theGroup),
- mySketchID(EID_UNKNOWN),
- myNeedToResolve(false),
- myEventsBlocked(false),
- myExistArc(false)
- {}
+ SketchSolver_Storage(SolverPtr theSolver);
/// \brief Change mapping between constraint from SketchPlugin and
/// a constraint applicable for corresponding solver.
/// \param theConstraint [in] original SketchPlugin constraint
- /// \param theSolverConstraint [in] solver's constraints
- SKETCHSOLVER_EXPORT void addConstraint(ConstraintPtr theConstraint,
- ConstraintWrapperPtr theSolverConstraints);
- /// \brief Change mapping between constraint from SketchPlugin and
- /// the list of constraints applicable for corresponding solver.
- /// \param theConstraint [in] original SketchPlugin constraint
- /// \param theSolverConstraints [in] list of solver's constraints
- SKETCHSOLVER_EXPORT virtual
- void addConstraint(ConstraintPtr theConstraint,
- std::list<ConstraintWrapperPtr> theSolverConstraints);
+ /// \param theSolverConstraint [in] solver's constraint
+ virtual void addConstraint(ConstraintPtr theConstraint,
+ ConstraintWrapperPtr theSolverConstraint);
+
+ /// \brief Add list of temporary constraints which will be destroyed
+ /// after the next solving of the set of constraints.
+ /// \param theSolverConstraint [in] solver's constraint
+ virtual void addTemporaryConstraint(const ConstraintWrapperPtr& theSolverConstraint) = 0;
+
+ /// \brief Change mapping feature from SketchPlugin and
+ /// the entity applicable for corresponding solver.
+ /// \param theFeature [in] original SketchPlugin feature
+ /// \param theSolverEntity [in] solver's entity, created outside
+ void addEntity(FeaturePtr theFeature,
+ EntityWrapperPtr theSolverEntity);
+
+ /// \brief Change mapping attribute of a feature and the entity
+ /// applicable for corresponding solver.
+ /// \param theAttribute [in] original attribute
+ /// \param theSolverEntity [in] solver's entity, created outside
+ void addEntity(AttributePtr theAttribute,
+ EntityWrapperPtr theSolverEntity);
/// \brief Convert feature to the form applicable for specific solver and map it
/// \param theFeature [in] feature to convert
- /// \param theGroup [in] id of the group where the feature should be placed
/// \param theForce [in] forced feature creation
/// \return \c true if the feature has been created or updated
- SKETCHSOLVER_EXPORT bool update(FeaturePtr theFeature,
- const GroupID& theGroup = GID_UNKNOWN, bool theForce = false);
+ virtual bool update(FeaturePtr theFeature, bool theForce = false) = 0;
/// \brief Convert attribute to the form applicable for specific solver and map it
/// \param theAttribute [in] attribute to convert
- /// \param theGroup [in] id of the group where the feature should be placed
/// \param theForce [in] forced feature creation
/// \return \c true if the attribute has been created or updated
- SKETCHSOLVER_EXPORT bool update(AttributePtr theAttribute,
- const GroupID& theGroup = GID_UNKNOWN, bool theForce = false);
+ virtual bool update(AttributePtr theAttribute, bool theForce = false) = 0;
/// \brief Returns constraint related to corresponding constraint
- SKETCHSOLVER_EXPORT
- const std::list<ConstraintWrapperPtr>& constraint(const ConstraintPtr& theConstraint) const;
+ const ConstraintWrapperPtr& constraint(const ConstraintPtr& theConstraint) const;
/// \brief Returns entity related to corresponding feature
- SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const FeaturePtr& theFeature) const;
+ const EntityWrapperPtr& entity(const FeaturePtr& theFeature) const;
/// \brief Returns entity related to corresponding attribute
- SKETCHSOLVER_EXPORT const EntityWrapperPtr& entity(const AttributePtr& theAttribute) const;
-
- /// \brief Return parsed sketch entity
- const EntityWrapperPtr& sketch() const;
- /// \brief Set parsed sketch entity.
- /// Be careful, this method does not update fields of the storage specific for the solver.
- /// Does not update if the sketch already exists.
- void setSketch(const EntityWrapperPtr& theSketch);
-
- /// \brief Mark two points as coincident
- virtual void addCoincidentPoints(EntityWrapperPtr theMaster, EntityWrapperPtr theSlave) = 0;
-
- /// \brief Shows the storage has any constraint twice
- virtual bool hasDuplicatedConstraint() const = 0;
+ const EntityWrapperPtr& entity(const AttributePtr& theAttribute) const;
/// \brief Removes constraint from the storage
/// \return \c true if the constraint and all its parameters are removed successfully
- SKETCHSOLVER_EXPORT bool removeConstraint(ConstraintPtr theConstraint);
+ virtual bool removeConstraint(ConstraintPtr theConstraint) = 0;
/// \brief Removes feature from the storage
- /// \return \c true if the feature and its attributes are removed successfully;
- /// \c false if the feature or any it attribute is used by remaining constraints.
- SKETCHSOLVER_EXPORT bool removeEntity(FeaturePtr theFeature);
+ void removeFeature(FeaturePtr theFeature);
/// \brief Removes attribute from the storage
- /// \return \c true if the attribute is not used by remaining features and constraints
- SKETCHSOLVER_EXPORT bool removeEntity(AttributePtr theAttribute);
+ void removeAttribute(AttributePtr theAttribute);
/// \brief Remove all features became invalid
- SKETCHSOLVER_EXPORT void removeInvalidEntities();
-
- /// \brief Check whether the feature or its attributes are used by this storage
- /// \param theFeature [in] feature to be checked
- /// \return \c true if the feature interacts with the storage
- bool isInteract(const FeaturePtr& theFeature) const;
- /// \brief Check whether the attribute is used by this storage
- /// \param theAttribute [in] attribute to be checked
- /// \return \c true if the attribute interacts with the storage
- bool isInteract(const AttributePtr& theAttribute) const;
+ virtual void removeInvalidEntities() = 0;
/// \brief Check the features is not removed
bool isConsistent() const;
bool isEmpty() const
{ return myConstraintMap.empty(); }
- /// \brief Check the entity is fixed.
- /// If the point is under verification, all coincident points are checked too.
- SKETCHSOLVER_EXPORT bool isFixed(EntityWrapperPtr theEntity) const;
-
/// \brief Shows the sketch should be resolved
virtual bool isNeedToResolve()
{ return myNeedToResolve; }
{ myNeedToResolve = theFlag; }
/// \brief Initialize solver by constraints, entities and parameters
- virtual void initializeSolver(SolverPtr theSolver) = 0;
+ virtual void initializeSolver() = 0;
/// \brief Return list of conflicting constraints
std::set<ObjectPtr> getConflictingConstraints(SolverPtr theSolver) const;
/// \brief Update SketchPlugin features after resolving constraints
- /// \param theFixedOnly [in] if \c true the fixed points will be updated only
- virtual void refresh(bool theFixedOnly = false) const = 0;
-
- /// \brief Check if some parameters or entities are returned
- /// to the current group after removing temporary constraints
- virtual void verifyFixed() = 0;
-
- /// \brief Calculate point on theBase entity. Value theCoeff is in [0.0 .. 1.0] and
- /// shows the distance from the start point.
- virtual EntityWrapperPtr calculateMiddlePoint(EntityWrapperPtr theBase,
- double theCoeff) = 0;
+ virtual void refresh() const = 0;
/// \brief Block or unblock events when refreshing features
- SKETCHSOLVER_EXPORT void blockEvents(bool isBlocked);
- /// \brief Shows the events are blocked for the features in the storage
- bool isEventsBlocked() const
- { return myEventsBlocked; }
+ void blockEvents(bool isBlocked);
-protected:
- /// \brief Change mapping feature from SketchPlugin and
- /// the entity applicable for corresponding solver.
- /// \param theFeature [in] original SketchPlugin feature
- /// \param theSolverEntity [in] solver's entity, created outside
- SKETCHSOLVER_EXPORT
- void addEntity(FeaturePtr theFeature,
- EntityWrapperPtr theSolverEntity);
+ /// \brief Subscribe for updates of features
+ /// \param theSubscriber [in] object which wants to revceive notifications
+ /// \param theGroup [in] group of updates features to be send
+ void subscribeUpdates(SketchSolver_Constraint* theSubscriber, const std::string& theGroup) const;
+ /// \brief Unsubscribe for updates of features
+ /// \param theSubscriber [in] object which does not want to revceive notifications anymore
+ void unsubscribeUpdates(SketchSolver_Constraint* theSubscriber) const;
- /// \brief Change mapping attribute of a feature and the entity
- /// applicable for corresponding solver.
- /// \param theAttribute [in] original attribute
- /// \param theSolverEntity [in] solver's entity, created outside
- SKETCHSOLVER_EXPORT
- void addEntity(AttributePtr theAttribute,
- EntityWrapperPtr theSolverEntity);
-
- /// \brief Update constraint's data
- /// \return \c true if any value is updated
- virtual bool update(ConstraintWrapperPtr theConstraint) = 0;
- /// \brief Update entity's data
- /// \return \c true if any value is updated
- virtual bool update(EntityWrapperPtr theEntity) = 0;
- /// \brief Update parameter's data
- /// \return \c true if the value of parameter is updated
- virtual bool update(ParameterWrapperPtr theParameter) = 0;
-
- /// \brief Remove constraint
- /// \return \c true if the constraint and all its parameters are removed successfully
- SKETCHSOLVER_EXPORT virtual bool remove(ConstraintWrapperPtr theConstraint);
- /// \brief Remove entity
- /// \return \c true if the entity and all its parameters are removed successfully
- SKETCHSOLVER_EXPORT virtual bool remove(EntityWrapperPtr theEntity);
- /// \brief Remove parameter
- /// \return \c true if the parameter has been removed
- virtual bool remove(ParameterWrapperPtr theParameter) = 0;
-
- /// \brief Remove point-point coincidence
- SKETCHSOLVER_EXPORT bool removeCoincidence(ConstraintWrapperPtr theConstraint);
-
- /// \brief Update the group for the given entity, its sub-entities and parameters
- virtual void changeGroup(EntityWrapperPtr theEntity, const GroupID& theGroup) = 0;
- /// \brief Update the group for the given parameter
- virtual void changeGroup(ParameterWrapperPtr theParam, const GroupID& theGroup) = 0;
-
- /// \brief Verify the feature or any its attribute is used by constraint
- SKETCHSOLVER_EXPORT bool isUsed(FeaturePtr theFeature) const;
- /// \brief Verify the attribute is used by constraint
- SKETCHSOLVER_EXPORT bool isUsed(AttributePtr theAttirubute) const;
-
- /// \brief Find arcs without corresponding entity applicable for the solver and build them
- SKETCHSOLVER_EXPORT void processArcs();
+ /// \brief Notify all subscribers about update of the feature
+ void notify(const FeaturePtr& theFeature) const;
- /// \brief Replace entities by others
- void replaceEntities(const std::map<EntityWrapperPtr, EntityWrapperPtr>& theChange);
-
-private:
- /// \brief Find the normal of the sketch
- EntityWrapperPtr getNormal() const;
+protected:
+ /// \brief Convert result to feature or attribute if theResult is linked to center of circle/arc
+ static void resultToFeatureOrAttribute(const ObjectPtr& theResult,
+ FeaturePtr& theFeature,
+ AttributePtr& theAttribute);
protected:
- EntityID mySketchID; ///< identifier of the sketch
- GroupID myGroupID; ///< identifier of the group, this storage belongs to
+ SolverPtr mySketchSolver; ///< Sketch solver, prepared in corresponding group
bool myNeedToResolve; ///< parameters are changed and group needs to be resolved
bool myEventsBlocked; ///< indicates that features do not send events
- bool myExistArc; ///< the storage has any point of arc but not full arc, need to add it
/// map SketchPlugin constraint to a list of solver's constraints
- std::map<ConstraintPtr, std::list<ConstraintWrapperPtr> > myConstraintMap;
+ std::map<ConstraintPtr, ConstraintWrapperPtr> myConstraintMap;
/// map SketchPlugin feature to solver's entity
- std::map<FeaturePtr, EntityWrapperPtr> myFeatureMap;
+ std::map<FeaturePtr, EntityWrapperPtr> myFeatureMap;
/// map attribute to solver's entity
- std::map<AttributePtr, EntityWrapperPtr> myAttributeMap;
-
- /// lists of coincident points (first is a master point, second is a set of slaves)
- CoincidentPointsMap myCoincidentPoints;
+ std::map<AttributePtr, EntityWrapperPtr> myAttributeMap;
- // to be able to update entities from constraints
- friend class SketchSolver_ConstraintDistance;
- friend class SketchSolver_ConstraintFixedArcRadius;
+ UpdaterPtr myUpdaters;
};
typedef std::shared_ptr<SketchSolver_Storage> StoragePtr;