aMirror.execute()
aSession.finishOperation()
#=========================================================================
+# Verify the simmetricity of all mirrored objects
+#=========================================================================
+aRefListC = aMirror.reflist("ConstraintEntityC")
+aListSize = aRefListB.size()
+aLineDirX = aLineEndPoint.x() - aLineStartPoint.x()
+aLineDirY = aLineEndPoint.y() - aLineStartPoint.y()
+
+for ind in range(0, aListSize):
+ aFeatureB = modelAPI_Feature(aRefListB.object(ind))
+ aFeatureC = modelAPI_Feature(aRefListC.object(ind))
+ assert(aFeatureB is not None)
+ assert(aFeatureC is not None)
+ assert(aFeatureB.getKind() == aFeatureC.getKind())
+ anAttributes = {}
+ print aFeatureB.getKind()
+ if (aFeatureB.getKind() == "SketchLine"):
+ anAttributes = {'StartPoint':'StartPoint', 'EndPoint':'EndPoint'}
+ elif (aFeatureB.getKind() == "SketchArc"):
+ anAttributes = {'ArcCenter':'ArcCenter', 'ArcStartPoint':'ArcEndPoint', 'ArcEndPoint':'ArcStartPoint'}
+
+ for key in anAttributes:
+ aPointB = geomDataAPI_Point2D(aFeatureB.attribute(key))
+ aPointC = geomDataAPI_Point2D(aFeatureC.attribute(anAttributes[key]))
+ aDirX = aPointC.x() - aPointB.x()
+ aDirY = aPointC.y() - aPointB.y()
+ aDot = aLineDirX * aDirX + aLineDirY * aDirY
+ assert(math.fabs(aDot) < 1.e-10)
+ aDirX = aLineEndPoint.x() - 0.5 * (aPointB.x() + aPointC.x())
+ aDirY = aLineEndPoint.y() - 0.5 * (aPointB.y() + aPointC.y())
+ aCross = aLineDirX * aDirY - aLineDirY * aDirX
+ assert(math.fabs(aCross) < 1.e-10)
+#=========================================================================
# End of test
#=========================================================================
#include <SketchPlugin_ConstraintEqual.h>
#include <SketchPlugin_ConstraintHorizontal.h>
#include <SketchPlugin_ConstraintLength.h>
+#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintParallel.h>
#include <SketchPlugin_ConstraintPerpendicular.h>
#include <SketchPlugin_ConstraintRadius.h>
#include <SketchPlugin_ConstraintVertical.h>
#include <ModelAPI_AttributeRefAttr.h>
+#include <ModelAPI_AttributeRefList.h>
#include <ModelAPI_Data.h>
#include <ModelAPI_Document.h>
#include <ModelAPI_Object.h>
return getType();
}
- if (aConstraintKind.compare(SketchPlugin_ConstraintEqual::ID()) == 0)
- {
+ if (aConstraintKind.compare(SketchPlugin_ConstraintEqual::ID()) == 0) {
static const int aConstrType[3] = {
SLVS_C_EQUAL_RADIUS,
SLVS_C_EQUAL_LINE_ARC_LEN,
return getType();
}
- if (aConstraintKind.compare(SketchPlugin_ConstraintTangent::ID()) == 0)
- {
+ if (aConstraintKind.compare(SketchPlugin_ConstraintTangent::ID()) == 0) {
static const int anArcPosDefault = 2;
static const int aLinePosDefault = 3;
int anArcPos = anArcPosDefault; // arc in tangency constraint should be placed before line
return getType();
}
+ if (aConstraintKind.compare(SketchPlugin_ConstraintMirror::ID()) == 0) {
+ int aNbAttrs = 0;
+ bool hasMirrorLine = false;
+ for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
+ AttributeRefListPtr anAttrRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr)));
+ if (anAttrRefList) {
+ aNbAttrs++;
+ myAttributesList[aNbAttrs] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+ }
+ else {
+ std::shared_ptr<ModelAPI_Attribute> anAttr =
+ aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
+ if (typeOfAttribute(anAttr) == LINE) {
+ hasMirrorLine = !hasMirrorLine;
+ myAttributesList[0] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
+ }
+ }
+ }
+ if (aNbAttrs == 2 && hasMirrorLine)
+ myType = SLVS_C_SYMMETRIC_LINE;
+ return getType();
+ }
+
/// \todo Implement other kind of constraints
return getType();
#include <SketchPlugin_Constraint.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintCoincidence.h>
+#include <SketchPlugin_ConstraintMirror.h>
#include <SketchPlugin_ConstraintRigid.h>
#include <SketchPlugin_Arc.h>
std::list<std::shared_ptr<ModelAPI_Attribute>>::const_iterator
anAttrIter = anAttrList.begin();
for ( ; anAttrIter != anAttrList.end(); anAttrIter++) {
- std::shared_ptr<ModelAPI_AttributeRefAttr> aCAttrRef =
+ AttributeRefListPtr aCAttrRefList =
+ std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*anAttrIter);
+ if (aCAttrRefList) {
+ std::list<ObjectPtr> anObjList = aCAttrRefList->list();
+ std::list<ObjectPtr>::iterator anIt = anObjList.begin();
+ for ( ; anIt != anObjList.end(); anIt++) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<SketchPlugin_Feature>(*anIt);
+ if (aFeature && myEntityFeatMap.find(aFeature) != myEntityFeatMap.end())
+ return true;
+ }
+ continue;
+ }
+ AttributeRefAttrPtr aCAttrRef =
std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anAttrIter);
if (!aCAttrRef || !aCAttrRef->isObject()) {
std::shared_ptr<ModelAPI_Attribute> anAttr =
if (myWorkplane.h == SLVS_E_UNKNOWN)
return false;
- if (theConstraint && theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID())
- return changeRigidConstraint(theConstraint);
+ if (theConstraint) {
+ if (theConstraint->getKind() == SketchPlugin_ConstraintRigid::ID())
+ return changeRigidConstraint(theConstraint);
+ if (theConstraint->getKind() == SketchPlugin_ConstraintMirror::ID())
+ return changeMirrorConstraint(theConstraint);
+ }
// Search this constraint in the current group to update it
ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
return true;
}
+// ============================================================================
+// Function: changeMirrorConstraint
+// Class: SketchSolver_ConstraintGroup
+// Purpose: create/update the "Mirror" constraint in the group
+// ============================================================================
+bool SketchSolver_ConstraintGroup::changeMirrorConstraint(
+ std::shared_ptr<SketchPlugin_Constraint> theConstraint)
+{
+ DataPtr aConstrData = theConstraint->data();
+
+ // Search this constraint in the current group to update it
+ ConstraintMap::const_iterator aConstrMapIter = myConstraintMap.find(theConstraint);
+ std::vector<Slvs_Constraint>::iterator aConstrIter;
+ if (aConstrMapIter != myConstraintMap.end()) {
+ int aConstrPos = Search(aConstrMapIter->second.front(), myConstraints);
+ aConstrIter = myConstraints.begin() + aConstrPos;
+ }
+
+ // Get constraint type and verify the constraint parameters are correct
+ SketchSolver_Constraint aConstraint(theConstraint);
+ int aConstrType = aConstraint.getType();
+ if (aConstrType == SLVS_C_UNKNOWN
+ || (aConstrMapIter != myConstraintMap.end() && aConstrIter->type != aConstrType))
+ return false;
+ const std::vector<std::string>& aConstraintAttributes = aConstraint.getAttributes();
+
+ Slvs_hEntity aMirrorLineEnt = SLVS_E_UNKNOWN;
+ AttributeRefAttrPtr aConstrAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
+ aConstrData->attribute(aConstraintAttributes[0]));
+ if (!aConstrAttr)
+ return false;
+
+ // Convert the object of the attribute to the feature
+ FeaturePtr aMirrorLineFeat;
+ if (aConstrAttr->isObject() && aConstrAttr->object()) {
+ ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
+ aConstrAttr->object());
+ if (!aRC)
+ return false;
+ std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
+ aMirrorLineFeat = aDoc->feature(aRC);
+ }
+ aMirrorLineEnt = aConstrAttr->isObject() ?
+ changeEntityFeature(aMirrorLineFeat) : changeEntity(aConstrAttr->attr());
+
+ if (aConstrMapIter == myConstraintMap.end()) { // Add new constraint
+ // Append symmetric constraint for each point of mirroring features
+ AttributeRefListPtr aBaseRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aConstrData->attribute(aConstraintAttributes[1]));
+ AttributeRefListPtr aMirroredRefList = std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
+ aConstrData->attribute(aConstraintAttributes[2]));
+ if (!aBaseRefList || !aMirroredRefList)
+ return false;
+
+ std::list<ObjectPtr> aBaseList = aBaseRefList->list();
+ std::list<ObjectPtr> aMirroredList = aMirroredRefList->list();
+ if (aBaseList.size() != aMirroredList.size())
+ return false;
+
+ myConstraintMap[theConstraint] = std::vector<Slvs_hEntity>();
+
+ FeaturePtr aBaseFeature, aMirrorFeature;
+ ResultConstructionPtr aRC;
+ std::list<ObjectPtr>::iterator aBaseIter = aBaseList.begin();
+ std::list<ObjectPtr>::iterator aMirIter = aMirroredList.begin();
+ for ( ; aBaseIter != aBaseList.end(); aBaseIter++, aMirIter++) {
+ aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aBaseIter);
+ aBaseFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aBaseIter);
+ aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aMirIter);
+ aMirrorFeature = aRC ? aRC->document()->feature(aRC) :
+ std::dynamic_pointer_cast<SketchPlugin_Feature>(*aMirIter);
+
+ if (!aBaseFeature || !aMirrorFeature ||
+ aBaseFeature->getKind() != aMirrorFeature->getKind())
+ return false;
+ Slvs_hEntity aBaseEnt = changeEntityFeature(aBaseFeature);
+ Slvs_hEntity aMirrorEnt = changeEntityFeature(aMirrorFeature);
+
+ if (aBaseFeature->getKind() == SketchPlugin_Point::ID()) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(++myConstrMaxID, myID, aConstrType,
+ myWorkplane.h, 0.0, aBaseEnt, aMirrorEnt, aMirrorLineEnt, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint].push_back(aConstraint.h);
+ } else {
+ int aBasePos = Search(aBaseEnt, myEntities);
+ int aMirrorPos = Search(aMirrorEnt, myEntities);
+ if (aBaseFeature->getKind() == SketchPlugin_Line::ID()) {
+ for (int ind = 0; ind < 2; ind++) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
+ myEntities[aBasePos].point[ind], myEntities[aMirrorPos].point[ind],
+ aMirrorLineEnt, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint].push_back(aConstraint.h);
+ }
+ } else if (aBaseFeature->getKind() == SketchPlugin_Circle::ID()) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
+ myEntities[aBasePos].point[0], myEntities[aMirrorPos].point[0],
+ aMirrorLineEnt, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint].push_back(aConstraint.h);
+ // Additional constraint for equal radii
+ Slvs_Constraint anEqRadConstr = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, SLVS_C_EQUAL_RADIUS, myWorkplane.h, 0.0,
+ SLVS_E_UNKNOWN, SLVS_E_UNKNOWN, aBaseEnt, aMirrorEnt);
+ myConstraints.push_back(anEqRadConstr);
+ myConstraintMap[theConstraint].push_back(anEqRadConstr.h);
+ } else if (aBaseFeature->getKind() == SketchPlugin_Arc::ID()) {
+ int aBaseArcInd[3] = {0, 1, 2}; // indices of points of arc, center corresponds center, first point corresponds last point
+ int aMirrorArcInd[3] = {0, 2, 1};
+ for (int ind = 0; ind < 2; ind++) {
+ Slvs_Constraint aConstraint = Slvs_MakeConstraint(
+ ++myConstrMaxID, myID, aConstrType, myWorkplane.h, 0.0,
+ myEntities[aBasePos].point[aBaseArcInd[ind]], myEntities[aMirrorPos].point[aMirrorArcInd[ind]],
+ aMirrorLineEnt, SLVS_E_UNKNOWN);
+ myConstraints.push_back(aConstraint);
+ myConstraintMap[theConstraint].push_back(aConstraint.h);
+ }
+ }
+ }
+ }
+ }
+
+ // Set the mirror line unchanged during constraint recalculation
+ if (aConstrAttr->isObject()) {
+ addTemporaryConstraintWhereDragged(aMirrorLineFeat->attribute(SketchPlugin_Line::START_ID()));
+ addTemporaryConstraintWhereDragged(aMirrorLineFeat->attribute(SketchPlugin_Line::END_ID()));
+ }
+ else addTemporaryConstraintWhereDragged(aConstrAttr->attr());
+ return true;
+}
+
// ============================================================================
// Function: changeEntity
// Class: SketchSolver_ConstraintGroup