diff --git a/src/Mod/Sketcher/App/Constraint.cpp b/src/Mod/Sketcher/App/Constraint.cpp index 416b2ca9d6..24d0959f84 100644 --- a/src/Mod/Sketcher/App/Constraint.cpp +++ b/src/Mod/Sketcher/App/Constraint.cpp @@ -53,7 +53,8 @@ Constraint::Constraint() Third(GeoUndef), ThirdPos(none), LabelDistance(10.f), - LabelPosition(0.f) + LabelPosition(0.f), + isDriving(true) { } @@ -69,7 +70,8 @@ Constraint::Constraint(const Constraint& from) Third(from.Third), ThirdPos(from.ThirdPos), LabelDistance(from.LabelDistance), - LabelPosition(from.LabelPosition) + LabelPosition(from.LabelPosition), + isDriving(from.isDriving) { } @@ -109,7 +111,8 @@ void Constraint::Save (Writer &writer) const << "Third=\"" << Third << "\" " << "ThirdPos=\"" << (int) ThirdPos << "\" " << "LabelDistance=\"" << LabelDistance << "\" " - << "LabelPosition=\"" << LabelPosition << "\" />" + << "LabelPosition=\"" << LabelPosition << "\" " + << "IsDriving=\"" << (int)isDriving << "\" />" << std::endl; } @@ -140,4 +143,7 @@ void Constraint::Restore(XMLReader &reader) if (reader.hasAttribute("LabelPosition")) LabelPosition = (float)reader.getAttributeAsFloat("LabelPosition"); + + if (reader.hasAttribute("IsDriving")) + isDriving = (bool)reader.getAttributeAsInteger("IsDriving"); } diff --git a/src/Mod/Sketcher/App/Constraint.h b/src/Mod/Sketcher/App/Constraint.h index e8bbfe67ef..82737de95d 100644 --- a/src/Mod/Sketcher/App/Constraint.h +++ b/src/Mod/Sketcher/App/Constraint.h @@ -95,6 +95,7 @@ public: PointPos ThirdPos; float LabelDistance; float LabelPosition; + bool isDriving; }; } //namespace Sketcher diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 9dff30f718..3b519e4d54 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -94,6 +94,11 @@ void Sketch::clear(void) for (std::vector::iterator it = Geoms.begin(); it != Geoms.end(); ++it) if (it->geo) delete it->geo; Geoms.clear(); + + // deleting the non-Driving constraints copied into this sketch + //for (std::vector::iterator it = NonDrivingConstraints.begin(); it != NonDrivingConstraints.end(); ++it) + // if (*it) delete *it; + Constrs.clear(); GCSsys.clear(); isInitMove = false; @@ -121,9 +126,9 @@ int Sketch::setUpSketch(const std::vector &GeoList, Geoms[i].external = true; // The Geoms list might be empty after an undo/redo - if (!Geoms.empty()) + if (!Geoms.empty()) { addConstraints(ConstraintList); - + } GCSsys.clearByTag(-1); GCSsys.declareUnknowns(Parameters); GCSsys.initSolution(); @@ -630,24 +635,69 @@ int Sketch::addConstraint(const Constraint *constraint) if(int(Geoms.size()) <= 0) throw Base::Exception("Sketch::addConstraint. Can't add constraint to a sketch with no geometry!"); int rtn = -1; + + ConstrDef c; + c.constr=const_cast(constraint); + c.driving=constraint->isDriving; + switch (constraint->Type) { case DistanceX: - if (constraint->FirstPos == none) // horizontal length of a line - rtn = addDistanceXConstraint(constraint->First,constraint->Value); - else if (constraint->Second == Constraint::GeoUndef) // point on fixed x-coordinate - rtn = addCoordinateXConstraint(constraint->First,constraint->FirstPos,constraint->Value); - else if (constraint->SecondPos != none) // point to point horizontal distance + if (constraint->FirstPos == none){ // horizontal length of a line + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addDistanceXConstraint(constraint->First,c.value); + } + else if (constraint->Second == Constraint::GeoUndef) {// point on fixed x-coordinate + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + + rtn = addCoordinateXConstraint(constraint->First,constraint->FirstPos,c.value); + } + else if (constraint->SecondPos != none) {// point to point horizontal distance + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addDistanceXConstraint(constraint->First,constraint->FirstPos, - constraint->Second,constraint->SecondPos,constraint->Value); + constraint->Second,constraint->SecondPos,c.value); + } break; case DistanceY: - if (constraint->FirstPos == none) // vertical length of a line - rtn = addDistanceYConstraint(constraint->First,constraint->Value); - else if (constraint->Second == Constraint::GeoUndef) // point on fixed y-coordinate - rtn = addCoordinateYConstraint(constraint->First,constraint->FirstPos,constraint->Value); - else if (constraint->SecondPos != none) // point to point vertical distance + if (constraint->FirstPos == none){ // vertical length of a line + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addDistanceYConstraint(constraint->First,c.value); + } + else if (constraint->Second == Constraint::GeoUndef){ // point on fixed y-coordinate + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + + rtn = addCoordinateYConstraint(constraint->First,constraint->FirstPos,c.value); + } + else if (constraint->SecondPos != none){ // point to point vertical distance + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addDistanceYConstraint(constraint->First,constraint->FirstPos, - constraint->Second,constraint->SecondPos,constraint->Value); + constraint->Second,constraint->SecondPos,c.value); + } break; case Horizontal: if (constraint->Second == Constraint::GeoUndef) // horizontal line @@ -680,11 +730,17 @@ int Sketch::addConstraint(const Constraint *constraint) rtn = addPerpendicularConstraint(constraint->First,constraint->Second); } else { //any other point-wise perpendicularity + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addAngleAtPointConstraint( constraint->First, constraint->FirstPos, constraint->Second, constraint->SecondPos, constraint->Third, constraint->ThirdPos, - constraint->Value, constraint->Type); + c.value, constraint->Type); } @@ -697,46 +753,101 @@ int Sketch::addConstraint(const Constraint *constraint) rtn = addTangentConstraint(constraint->First,constraint->Second); } else { //any other point-wise tangency (endpoint-to-curve, endpoint-to-endpoint, tangent-via-point) + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addAngleAtPointConstraint( constraint->First, constraint->FirstPos, constraint->Second, constraint->SecondPos, constraint->Third, constraint->ThirdPos, - constraint->Value, constraint->Type); + c.value, constraint->Type); } break; case Distance: - if (constraint->SecondPos != none) // point to point distance + if (constraint->SecondPos != none){ // point to point distance + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); rtn = addDistanceConstraint(constraint->First,constraint->FirstPos, constraint->Second,constraint->SecondPos, - constraint->Value); - else if (constraint->Second != Constraint::GeoUndef) { - if (constraint->FirstPos != none) // point to line distance - rtn = addDistanceConstraint(constraint->First,constraint->FirstPos, - constraint->Second,constraint->Value); - else // line to line distance (not implemented yet) - rtn = addDistanceConstraint(constraint->First,constraint->Second,constraint->Value); + c.value); + } + else if (constraint->Second != Constraint::GeoUndef) { + if (constraint->FirstPos != none) { // point to line distance + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addDistanceConstraint(constraint->First,constraint->FirstPos, + constraint->Second,c.value); + } + } + else {// line length + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + + rtn = addDistanceConstraint(constraint->First,c.value); } - else // line length - rtn = addDistanceConstraint(constraint->First,constraint->Value); break; case Angle: if (constraint->Third != Constraint::GeoUndef){ + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addAngleAtPointConstraint ( constraint->First, constraint->FirstPos, constraint->Second, constraint->SecondPos, constraint->Third, constraint->ThirdPos, - constraint->Value, constraint->Type); - } else if (constraint->SecondPos != none) // angle between two lines (with explicit start points) + c.value, constraint->Type); + } else if (constraint->SecondPos != none){ // angle between two lines (with explicit start points) + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addAngleConstraint(constraint->First,constraint->FirstPos, - constraint->Second,constraint->SecondPos,constraint->Value); - else if (constraint->Second != Constraint::GeoUndef) // angle between two lines - rtn = addAngleConstraint(constraint->First,constraint->Second,constraint->Value); - else if (constraint->First != Constraint::GeoUndef) // orientation angle of a line - rtn = addAngleConstraint(constraint->First,constraint->Value); + constraint->Second,constraint->SecondPos,c.value); + } + else if (constraint->Second != Constraint::GeoUndef){ // angle between two lines + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addAngleConstraint(constraint->First,constraint->Second,c.value); + } + else if (constraint->First != Constraint::GeoUndef) {// orientation angle of a line + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addAngleConstraint(constraint->First,c.value); + } break; case Radius: - rtn = addRadiusConstraint(constraint->First, constraint->Value); + { + c.value = new double(constraint->Value); + if(c.driving) + FixParameters.push_back(c.value); + else + Parameters.push_back(c.value); + rtn = addRadiusConstraint(constraint->First, c.value); break; + } case Equal: rtn = addEqualConstraint(constraint->First,constraint->Second); break; @@ -766,62 +877,76 @@ int Sketch::addConstraint(const Constraint *constraint) } break; case SnellsLaw: + { + c.value = new double(constraint->Value); + c.secondvalue = new double(constraint->Value); + + if(c.driving) { + FixParameters.push_back(c.value); + FixParameters.push_back(c.secondvalue); + } + else { + Parameters.push_back(c.value); + Parameters.push_back(c.secondvalue); + } + //assert(constraint->ThirdPos==none); //will work anyway... rtn = addSnellsLawConstraint(constraint->First, constraint->FirstPos, constraint->Second, constraint->SecondPos, constraint->Third, - constraint->Value); + c.value, c.secondvalue); + } break; case None: break; } + + Constrs.push_back(c); return rtn; } int Sketch::addConstraints(const std::vector &ConstraintList) { int rtn = -1; + for (std::vector::const_iterator it = ConstraintList.begin();it!=ConstraintList.end();++it) rtn = addConstraint (*it); return rtn; } -int Sketch::addCoordinateXConstraint(int geoId, PointPos pos, double value) +int Sketch::addCoordinateXConstraint(int geoId, PointPos pos, double * value) { geoId = checkGeoId(geoId); int pointId = getPointId(geoId, pos); if (pointId >= 0 && pointId < int(Points.size())) { - double *val = new double(value); - FixParameters.push_back(val); + GCS::Point &p = Points[pointId]; int tag = ++ConstraintsCounter; - GCSsys.addConstraintCoordinateX(p, val, tag); + GCSsys.addConstraintCoordinateX(p, value, tag); return ConstraintsCounter; } return -1; } -int Sketch::addCoordinateYConstraint(int geoId, PointPos pos, double value) +int Sketch::addCoordinateYConstraint(int geoId, PointPos pos, double * value) { geoId = checkGeoId(geoId); int pointId = getPointId(geoId, pos); if (pointId >= 0 && pointId < int(Points.size())) { - double *val = new double(value); - FixParameters.push_back(val); GCS::Point &p = Points[pointId]; int tag = ++ConstraintsCounter; - GCSsys.addConstraintCoordinateY(p, val, tag); + GCSsys.addConstraintCoordinateY(p, value, tag); return ConstraintsCounter; } return -1; } -int Sketch::addDistanceXConstraint(int geoId, double value) +int Sketch::addDistanceXConstraint(int geoId, double * value) { geoId = checkGeoId(geoId); @@ -830,15 +955,12 @@ int Sketch::addDistanceXConstraint(int geoId, double value) GCS::Line &l = Lines[Geoms[geoId].index]; - FixParameters.push_back(new double(value)); - double *diff = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintDifference(l.p1.x, l.p2.x, diff, tag); + GCSsys.addConstraintDifference(l.p1.x, l.p2.x, value, tag); return ConstraintsCounter; } -int Sketch::addDistanceYConstraint(int geoId, double value) +int Sketch::addDistanceYConstraint(int geoId, double * value) { geoId = checkGeoId(geoId); @@ -847,15 +969,12 @@ int Sketch::addDistanceYConstraint(int geoId, double value) GCS::Line &l = Lines[Geoms[geoId].index]; - FixParameters.push_back(new double(value)); - double *diff = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintDifference(l.p1.y, l.p2.y, diff, tag); + GCSsys.addConstraintDifference(l.p1.y, l.p2.y, value, tag); return ConstraintsCounter; } -int Sketch::addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value) +int Sketch::addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value) { geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -868,17 +987,14 @@ int Sketch::addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointP GCS::Point &p1 = Points[pointId1]; GCS::Point &p2 = Points[pointId2]; - FixParameters.push_back(new double(value)); - double *difference = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintDifference(p1.x, p2.x, difference, tag); + GCSsys.addConstraintDifference(p1.x, p2.x, value, tag); return ConstraintsCounter; } return -1; } -int Sketch::addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value) +int Sketch::addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value) { geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -891,11 +1007,8 @@ int Sketch::addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointP GCS::Point &p1 = Points[pointId1]; GCS::Point &p2 = Points[pointId2]; - FixParameters.push_back(new double(value)); - double *difference = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintDifference(p1.y, p2.y, difference, tag); + GCSsys.addConstraintDifference(p1.y, p2.y, value, tag); return ConstraintsCounter; } return -1; @@ -1148,7 +1261,7 @@ int Sketch::addAngleAtPointConstraint( int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3, - double value, + double * value, ConstraintType cTyp) { @@ -1205,9 +1318,7 @@ int Sketch::addAngleAtPointConstraint( p2 = &(Points[pointId]); } - // add the parameter for the angle - FixParameters.push_back(new double(0.0)); - double *angle = FixParameters[FixParameters.size()-1]; + double *angle = value; //For tangency/perpendicularity, we don't just copy the angle. //The angle stored for tangency/perpendicularity is offset, so that the options @@ -1215,9 +1326,8 @@ int Sketch::addAngleAtPointConstraint( // Use autodetect then. //The same functionality is implemented in SketchObject.cpp, where // it is used to permanently lock down the autodecision. - if (cTyp == Angle) - *angle = value; - else { + if (cTyp != Angle) + { //The same functionality is implemented in SketchObject.cpp, where // it is used to permanently lock down the autodecision. double angleOffset = 0.0;//the difference between the datum value and the actual angle to apply. (datum=angle+offset) @@ -1225,7 +1335,7 @@ int Sketch::addAngleAtPointConstraint( if (cTyp == Tangent) {angleOffset = -M_PI/2; angleDesire = 0.0;} if (cTyp == Perpendicular) {angleOffset = 0; angleDesire = M_PI/2;} - if (value==0.0) {//autodetect tangency internal/external (and same for perpendicularity) + if (*value==0.0) {//autodetect tangency internal/external (and same for perpendicularity) double angleErr = GCSsys.calculateAngleViaPoint(*crv1, *crv2, p) - angleDesire; //bring angleErr to -pi..pi if (angleErr > M_PI) angleErr -= M_PI*2; @@ -1237,10 +1347,9 @@ int Sketch::addAngleAtPointConstraint( *angle = angleDesire; } else - *angle = value-angleOffset; + *angle = *value-angleOffset; } - int tag = -1; if(e2c) tag = Sketch::addPointOnObjectConstraint(geoId1, pos1, geoId2);//increases ConstraintsCounter @@ -1256,7 +1365,7 @@ int Sketch::addAngleAtPointConstraint( } // line length constraint -int Sketch::addDistanceConstraint(int geoId, double value) +int Sketch::addDistanceConstraint(int geoId, double * value) { geoId = checkGeoId(geoId); @@ -1265,31 +1374,13 @@ int Sketch::addDistanceConstraint(int geoId, double value) GCS::Line &l = Lines[Geoms[geoId].index]; - // add the parameter for the length - FixParameters.push_back(new double(value)); - double *distance = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintP2PDistance(l.p1, l.p2, distance, tag); + GCSsys.addConstraintP2PDistance(l.p1, l.p2, value, tag); return ConstraintsCounter; } -// line to line distance constraint -int Sketch::addDistanceConstraint(int geoId1, int geoId2, double value) -{ - //geoId1 = checkGeoId(geoId1); - //geoId2 = checkGeoId(geoId2); - - //assert(Geoms[geoId1].type == Line); - //assert(Geoms[geoId2].type == Line); - - Base::Console().Warning("Line to line distance constraints are not implemented yet.\n"); - - return -1; -} - // point to line distance constraint -int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double value) +int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double * value) { geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -1303,19 +1394,15 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double GCS::Point &p1 = Points[pointId1]; GCS::Line &l2 = Lines[Geoms[geoId2].index]; - // add the parameter for the distance - FixParameters.push_back(new double(value)); - double *distance = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintP2LDistance(p1, l2, distance, tag); + GCSsys.addConstraintP2LDistance(p1, l2, value, tag); return ConstraintsCounter; } return -1; } // point to point distance constraint -int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value) +int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value) { geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -1328,74 +1415,56 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPo GCS::Point &p1 = Points[pointId1]; GCS::Point &p2 = Points[pointId2]; - // add the parameter for the distance - FixParameters.push_back(new double(value)); - double *distance = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintP2PDistance(p1, p2, distance, tag); + GCSsys.addConstraintP2PDistance(p1, p2, value, tag); return ConstraintsCounter; } return -1; } -int Sketch::addRadiusConstraint(int geoId, double value) +int Sketch::addRadiusConstraint(int geoId, double * value) { geoId = checkGeoId(geoId); if (Geoms[geoId].type == Circle) { GCS::Circle &c = Circles[Geoms[geoId].index]; - // add the parameter for the radius - FixParameters.push_back(new double(value)); - double *radius = FixParameters[FixParameters.size()-1]; int tag = ++ConstraintsCounter; - GCSsys.addConstraintCircleRadius(c, radius, tag); + GCSsys.addConstraintCircleRadius(c, value, tag); return ConstraintsCounter; } else if (Geoms[geoId].type == Arc) { GCS::Arc &a = Arcs[Geoms[geoId].index]; - // add the parameter for the radius - FixParameters.push_back(new double(value)); - double *radius = FixParameters[FixParameters.size()-1]; int tag = ++ConstraintsCounter; - GCSsys.addConstraintArcRadius(a, radius, tag); + GCSsys.addConstraintArcRadius(a, value, tag); return ConstraintsCounter; } return -1; } // line orientation angle constraint -int Sketch::addAngleConstraint(int geoId, double value) +int Sketch::addAngleConstraint(int geoId, double * value) { geoId = checkGeoId(geoId); if (Geoms[geoId].type == Line) { GCS::Line &l = Lines[Geoms[geoId].index]; - // add the parameter for the angle - FixParameters.push_back(new double(value)); - double *angle = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintP2PAngle(l.p1, l.p2, angle, tag); + GCSsys.addConstraintP2PAngle(l.p1, l.p2, value, tag); return ConstraintsCounter; } else if (Geoms[geoId].type == Arc) { GCS::Arc &a = Arcs[Geoms[geoId].index]; - // add the parameter for the angle - FixParameters.push_back(new double(value)); - double *angle = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintL2LAngle(a.center, a.start, a.center, a.end, angle, tag); + GCSsys.addConstraintL2LAngle(a.center, a.start, a.center, a.end, value, tag); return ConstraintsCounter; } return -1; } // line to line angle constraint -int Sketch::addAngleConstraint(int geoId1, int geoId2, double value) +int Sketch::addAngleConstraint(int geoId1, int geoId2, double * value) { geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -1407,17 +1476,13 @@ int Sketch::addAngleConstraint(int geoId1, int geoId2, double value) GCS::Line &l1 = Lines[Geoms[geoId1].index]; GCS::Line &l2 = Lines[Geoms[geoId2].index]; - // add the parameter for the angle - FixParameters.push_back(new double(value)); - double *angle = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintL2LAngle(l1, l2, angle, tag); + GCSsys.addConstraintL2LAngle(l1, l2, value, tag); return ConstraintsCounter; } // line to line angle constraint (with explicitly given start points) -int Sketch::addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value) +int Sketch::addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value) { geoId1 = checkGeoId(geoId1); geoId2 = checkGeoId(geoId2); @@ -1447,12 +1512,8 @@ int Sketch::addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos p if (l1p1 == 0 || l2p1 == 0) return -1; - // add the parameter for the angle - FixParameters.push_back(new double(value)); - double *angle = FixParameters[FixParameters.size()-1]; - int tag = ++ConstraintsCounter; - GCSsys.addConstraintL2LAngle(*l1p1, *l1p2, *l2p1, *l2p2, angle, tag); + GCSsys.addConstraintL2LAngle(*l1p1, *l1p2, *l2p1, *l2p2, value, tag); return ConstraintsCounter; } @@ -1644,7 +1705,9 @@ int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointP int Sketch::addSnellsLawConstraint(int geoIdRay1, PointPos posRay1, int geoIdRay2, PointPos posRay2, int geoIdBnd, - double n2divn1) + double * value, + double * secondvalue + ) { geoIdRay1 = checkGeoId(geoIdRay1); @@ -1675,12 +1738,13 @@ int Sketch::addSnellsLawConstraint(int geoIdRay1, PointPos posRay1, GCS::Point &p1 = Points[pointId1]; GCS::Point &p2 = Points[pointId2]; - // add the parameters (refractive indexes) - FixParameters.push_back(new double(0.0)); - double *n1 = FixParameters[FixParameters.size()-1]; - FixParameters.push_back(new double(0.0)); - double *n2 = FixParameters[FixParameters.size()-1]; - + // add the parameters (refractive indexes) + // n1 uses the place hold by n2divn1, so that is retrivable in updateNonDrivingConstraints + double *n1 = value; + double *n2 = secondvalue; + + double n2divn1=*value; + if ( abs(n2divn1) >= 1.0 ){ *n2 = n2divn1; *n1 = 1.0; @@ -1993,6 +2057,23 @@ bool Sketch::updateGeometry() return true; } +bool Sketch::updateNonDrivingConstraints() +{ + for (std::vector::iterator it = Constrs.begin();it!=Constrs.end();++it){ + if(!(*it).driving) { + if((*it).constr->Type==SnellsLaw) { + double n1 = *((*it).value); + double n2 = *((*it).secondvalue); + + (*it).constr->Value = n2/n1; + } + else + (*it).constr->Value=*((*it).value); + } + } + return true; +} + // solving ========================================================== int Sketch::solve(void) @@ -2043,6 +2124,9 @@ int Sketch::solve(void) GCSsys.undoSolution(); updateGeometry(); Base::Console().Warning("Invalid solution from %s solver.\n", solvername.c_str()); + }else + { + updateNonDrivingConstraints(); } } else { valid_solution = false; diff --git a/src/Mod/Sketcher/App/Sketch.h b/src/Mod/Sketcher/App/Sketch.h index dd91aa075e..fff2e63dc2 100644 --- a/src/Mod/Sketcher/App/Sketch.h +++ b/src/Mod/Sketcher/App/Sketch.h @@ -135,14 +135,14 @@ public: /// add one constraint to the sketch int addConstraint(const Constraint *constraint); /// add a fixed coordinate constraint to a point - int addCoordinateXConstraint(int geoId, PointPos pos, double value); - int addCoordinateYConstraint(int geoId, PointPos pos, double value); + int addCoordinateXConstraint(int geoId, PointPos pos, double * value); + int addCoordinateYConstraint(int geoId, PointPos pos, double * value); /// add a horizontal distance constraint to two points or line ends - int addDistanceXConstraint(int geoId, double value); - int addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value); + int addDistanceXConstraint(int geoId, double * value); + int addDistanceXConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value); /// add a vertical distance constraint to two points or line ends - int addDistanceYConstraint(int geoId, double value); - int addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value); + int addDistanceYConstraint(int geoId, double * value); + int addDistanceYConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value); /// add a horizontal constraint to a geometry int addHorizontalConstraint(int geoId); int addHorizontalConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2); @@ -152,10 +152,9 @@ public: /// add a coincident constraint to two points of two geometries int addPointCoincidentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2); /// add a length or distance constraint - int addDistanceConstraint(int geoId1, double value); - int addDistanceConstraint(int geoId1, int geoId2, double value); - int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double value); - int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value); + int addDistanceConstraint(int geoId1, double * value); + int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, double * value); + int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value); /// add a parallel constraint between two lines int addParallelConstraint(int geoId1, int geoId2); /// add a perpendicular constraint between two lines @@ -166,14 +165,14 @@ public: int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3, - double value, + double * value, ConstraintType cTyp); /// add a radius constraint on a circle or an arc - int addRadiusConstraint(int geoId, double value); + int addRadiusConstraint(int geoId, double * value); /// add an angle constraint on a line or between two lines - int addAngleConstraint(int geoId, double value); - int addAngleConstraint(int geoId1, int geoId2, double value); - int addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double value); + int addAngleConstraint(int geoId, double * value); + int addAngleConstraint(int geoId1, int geoId2, double * value); + int addAngleConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value); /// add angle-via-point constraint between any two curves int addAngleViaPointConstraint(int geoId1, int geoId2, int geoId3, PointPos pos3, double value); /// add an equal length or radius constraints between two lines or between circles and arcs @@ -188,7 +187,8 @@ public: int addSnellsLawConstraint(int geoIdRay1, PointPos posRay1, int geoIdRay2, PointPos posRay2, int geoIdBnd, - double n2divn1); + double * value, + double * second); //@} /// Internal Alignment constraints @@ -238,8 +238,17 @@ protected: int midPointId; // index in Points of the start point of this geometry int endPointId; // index in Points of the end point of this geometry }; + + struct ConstrDef { + ConstrDef() : driving(true) {} + Constraint * constr; // pointer to the constraint + bool driving; + double * value; + double * secondvalue; // this is needed for SnellsLaw + }; std::vector Geoms; + std::vector Constrs; GCS::System GCSsys; int ConstraintsCounter; std::vector Conflicting; @@ -264,6 +273,7 @@ protected: private: bool updateGeometry(void); + bool updateNonDrivingConstraints(void); /// checks if the index bounds and converts negative indices to positive int checkGeoId(int geoId); diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 35f6fa0bc7..2e5d017466 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -219,6 +219,60 @@ int SketchObject::setDatum(int ConstrId, double Datum) return err; } +int SketchObject::setDriving(int ConstrId, bool isdriving) +{ + const std::vector &vals = this->Constraints.getValues(); + + if (ConstrId < 0 || ConstrId >= int(vals.size())) + return -1; + + ConstraintType type = vals[ConstrId]->Type; + + if (type != Distance && + type != DistanceX && + type != DistanceY && + type != Radius && + type != Angle && + type != SnellsLaw) + return -1; + + // copy the list + std::vector newVals(vals); + // clone the changed Constraint + Constraint *constNew = vals[ConstrId]->clone(); + constNew->isDriving = isdriving; + newVals[ConstrId] = constNew; + this->Constraints.setValues(newVals); + delete constNew; + + int err = solve(); + if (err) + this->Constraints.setValues(vals); + + return err; +} + +int SketchObject::getDriving(int ConstrId, bool &isdriving) +{ + const std::vector &vals = this->Constraints.getValues(); + + if (ConstrId < 0 || ConstrId >= int(vals.size())) + return -1; + + ConstraintType type = vals[ConstrId]->Type; + + if (type != Distance && + type != DistanceX && + type != DistanceY && + type != Radius && + type != Angle && + type != SnellsLaw) + return -1; + + isdriving=vals[ConstrId]->isDriving; + return 0; +} + int SketchObject::movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative) { Sketch sketch; diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 6ac6207f54..0be407c5e0 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -110,6 +110,10 @@ public: int solve(); /// set the datum of a Distance or Angle constraint and solve int setDatum(int ConstrId, double Datum); + /// set the driving status of this constraint and solve + int setDriving(int ConstrId, bool isdriving); + /// get the driving status of this constraint + int getDriving(int ConstrId, bool &isdriving); /// move this point to a new location and solve int movePoint(int GeoId, PointPos PosId, const Base::Vector3d& toPoint, bool relative=false); /// retrieves the coordinates of a point diff --git a/src/Mod/Sketcher/App/SketchObjectPy.xml b/src/Mod/Sketcher/App/SketchObjectPy.xml index 933ec00463..ccc48516d0 100644 --- a/src/Mod/Sketcher/App/SketchObjectPy.xml +++ b/src/Mod/Sketcher/App/SketchObjectPy.xml @@ -78,6 +78,16 @@ Get the value of a datum constraint + + + set the Driving status of a datum constraint + + + + + Get the Driving status of a datum constraint + + diff --git a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp index 943380d997..62fe6738f6 100644 --- a/src/Mod/Sketcher/App/SketchObjectPyImp.cpp +++ b/src/Mod/Sketcher/App/SketchObjectPyImp.cpp @@ -568,6 +568,42 @@ PyObject* SketchObjectPy::getDatum(PyObject *args) return new Base::QuantityPy(new Base::Quantity(datum)); } +PyObject* SketchObjectPy::setDriving(PyObject *args) +{ + PyObject* driving; + int constrid; + + if (!PyArg_ParseTuple(args, "iO!", &constrid, &PyBool_Type, &driving)) + return 0; + + if (this->getSketchObjectPtr()->setDriving(constrid, PyObject_IsTrue(driving) ? true : false)) { + std::stringstream str; + str << "Not able set Driving for constraint with the given index: " << constrid; + PyErr_SetString(PyExc_ValueError, str.str().c_str()); + return 0; + } + + Py_Return; +} + +PyObject* SketchObjectPy::getDriving(PyObject *args) +{ + int constrid; + bool driving; + + if (!PyArg_ParseTuple(args, "i", &constrid)) + return 0; + + SketchObject* obj = this->getSketchObjectPtr(); + if (this->getSketchObjectPtr()->getDriving(constrid, driving)) { + PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); + return 0; + } + + return Py::new_reference_to(Py::Boolean(driving)); +} + + PyObject* SketchObjectPy::movePoint(PyObject *args) { PyObject *pcObj; diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 4534260f4a..f2c9ab670c 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -158,7 +158,7 @@ void openEditDatumDialog(Sketcher::SketchObject* sketch, int ConstrNbr) } // Utility method to avoid repeating the same code over and over again -void finishDistanceConstraint(Gui::Command* cmd, Sketcher::SketchObject* sketch) +void finishDistanceConstraint(Gui::Command* cmd, Sketcher::SketchObject* sketch, bool isDriven=true) { // Get the latest constraint const std::vector &ConStr = sketch->Constraints.getValues(); @@ -179,11 +179,11 @@ void finishDistanceConstraint(Gui::Command* cmd, Sketcher::SketchObject* sketch) bool show = hGrp->GetBool("ShowDialogOnDistanceConstraint", true); // Ask for the value of the distance immediately - if (show) { + if (show && isDriven) { openEditDatumDialog(sketch, ConStr.size() - 1); } else { - // now dialog was shown so commit the command + // no dialog was shown so commit the command cmd->commitCommand(); } @@ -191,17 +191,18 @@ void finishDistanceConstraint(Gui::Command* cmd, Sketcher::SketchObject* sketch) cmd->getSelection().clearSelection(); } +void showNoConstraintBetweenExternal() +{ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Cannot add a constraint between two external geometries!")); +} + bool checkBothExternal(int GeoId1, int GeoId2) { if (GeoId1 == Constraint::GeoUndef || GeoId2 == Constraint::GeoUndef) return false; - else if (GeoId1 < 0 && GeoId2 < 0) { - QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("Cannot add a constraint between two external geometries!")); - return true; - } else - return false; + return (GeoId1 < 0 && GeoId2 < 0); } void getIdsFromName(const std::string &name, const Sketcher::SketchObject* Obj, @@ -711,9 +712,9 @@ void CmdSketcherConstrainLock::activated(int iMsg) Sketcher::PointPos PosId; getIdsFromName(SubNames[0], Obj, GeoId, PosId); - if (isEdge(GeoId,PosId) || GeoId < 0) { + if (isEdge(GeoId,PosId) || (GeoId < 0 && GeoId >= -2)) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - QObject::tr("Select one vertex from the sketch.")); + QObject::tr("Select one vertex from the sketch other than the origin.")); return; } @@ -728,6 +729,16 @@ void CmdSketcherConstrainLock::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%f)) ", selection[0].getFeatName(),GeoId,PosId,pnt.y); + if (GeoId < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-2,"False"); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + } + // finish the transaction and update commitCommand(); updateActive(); @@ -885,10 +896,10 @@ void CmdSketcherConstrainDistance::activated(int iMsg) getIdsFromName(SubNames[0], Obj, GeoId1, PosId1); if (SubNames.size() == 2) getIdsFromName(SubNames[1], Obj, GeoId2, PosId2); - - if (checkBothExternal(GeoId1, GeoId2)) - return; - else if (isVertex(GeoId1,PosId1) && (GeoId2 == -2 || GeoId2 == -1)) { + + bool bothexternal=checkBothExternal(GeoId1, GeoId2); + + if (isVertex(GeoId1,PosId1) && (GeoId2 == -2 || GeoId2 == -1)) { std::swap(GeoId1,GeoId2); std::swap(PosId1,PosId2); } @@ -920,8 +931,16 @@ void CmdSketcherConstrainDistance::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,(pnt2-pnt1).Length()); } - - finishDistanceConstraint(this, Obj); + + if (bothexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); return; } else if ((isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) || @@ -945,15 +964,23 @@ void CmdSketcherConstrainDistance::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,GeoId2,ActDist); - finishDistanceConstraint(this, Obj); + if (bothexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } } else if (isEdge(GeoId1,PosId1)) { // line length - if (GeoId1 < 0) { + if (GeoId1 < 0 && GeoId1 >= -2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - GeoId1 < 2 ? QObject::tr("Cannot add a length constraint on an external geometry!") - : QObject::tr("Cannot add a length constraint on an axis!")); + QObject::tr("Cannot add a length constraint on an axis!")); return; } @@ -967,8 +994,17 @@ void CmdSketcherConstrainDistance::activated(int iMsg) Gui::Command::doCommand( Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Distance',%d,%f)) ", selection[0].getFeatName(),GeoId1,ActLength); - - finishDistanceConstraint(this, Obj); + + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } } @@ -1035,8 +1071,10 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg) int cnt = 0; for (int iPnt = 0; iPnt < points.size(); iPnt++) { for (int iCrv = 0; iCrv < curves.size(); iCrv++) { - if (checkBothExternal(points[iPnt].GeoId, curves[iCrv].GeoId)) + if (checkBothExternal(points[iPnt].GeoId, curves[iCrv].GeoId)){ + showNoConstraintBetweenExternal(); continue; + } if (points[iPnt].GeoId == curves[iCrv].GeoId) continue; //constraining a point of an element onto the element is a bad idea... cnt++; @@ -1112,9 +1150,9 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) if (SubNames.size() == 2) getIdsFromName(SubNames[1], Obj, GeoId2, PosId2); - if (checkBothExternal(GeoId1, GeoId2)) - return; - else if (GeoId2 == -1 || GeoId2 == -2) { + bool bothexternal=checkBothExternal(GeoId1, GeoId2); + + if (GeoId2 == -1 || GeoId2 == -2) { std::swap(GeoId1,GeoId2); std::swap(PosId1,PosId2); } @@ -1137,15 +1175,23 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,ActLength); - finishDistanceConstraint(this, Obj); + if (bothexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } else if (isEdge(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // horizontal length of a line - if (GeoId1 < 0) { + if (GeoId1 < 0 && GeoId1 >= -2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - GeoId1 < -2 ? QObject::tr("Cannot add a horizontal length constraint on an external geometry!") - : QObject::tr("Cannot add a horizontal length constraint on an axis!")); + QObject::tr("Cannot add a horizontal length constraint on an axis!")); return; } @@ -1160,16 +1206,24 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%f)) ", selection[0].getFeatName(),GeoId1,ActLength); - finishDistanceConstraint(this, Obj); + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } } else if (isVertex(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // point on fixed x-coordinate - if (GeoId1 < 0) { + if (GeoId1 < 0 && GeoId1 >= -2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - GeoId1 < -2 ? QObject::tr("Cannot add a fixed x-coordinate constraint on an external geometry!") - : QObject::tr("Cannot add a fixed x-coordinate constraint on the root point!")); + QObject::tr("Cannot add a fixed x-coordinate constraint on the root point!")); return; } @@ -1180,8 +1234,17 @@ void CmdSketcherConstrainDistanceX::activated(int iMsg) Gui::Command::doCommand( Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceX',%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,ActX); - - finishDistanceConstraint(this, Obj); + + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } @@ -1240,9 +1303,9 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) if (SubNames.size() == 2) getIdsFromName(SubNames[1], Obj, GeoId2, PosId2); - if (checkBothExternal(GeoId1, GeoId2)) - return; - else if (GeoId2 == -1 || GeoId2 == -2) { + bool bothexternal=checkBothExternal(GeoId1, GeoId2); + + if (GeoId2 == -1 || GeoId2 == -2) { std::swap(GeoId1,GeoId2); std::swap(PosId1,PosId2); } @@ -1263,15 +1326,23 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,ActLength); - finishDistanceConstraint(this, Obj); + if (bothexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } else if (isEdge(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // vertical length of a line - if (GeoId1 < 0) { + if (GeoId1 < 0 && GeoId1 >= -2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - GeoId1 < -2 ? QObject::tr("Cannot add a vertical length constraint on an external geometry!") - : QObject::tr("Cannot add a vertical length constraint on an axis!")); + QObject::tr("Cannot add a vertical length constraint on an axis!")); return; } @@ -1286,16 +1357,24 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%f)) ", selection[0].getFeatName(),GeoId1,ActLength); - finishDistanceConstraint(this, Obj); + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } } else if (isVertex(GeoId1,PosId1) && GeoId2 == Constraint::GeoUndef) { // point on fixed y-coordinate - if (GeoId1 < 0) { + if (GeoId1 < 0 && GeoId1 >= -2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - GeoId1 < -2 ? QObject::tr("Cannot add a fixed y-coordinate constraint on an external geometry!") - : QObject::tr("Cannot add a fixed y-coordinate constraint on the root point!")); + QObject::tr("Cannot add a fixed y-coordinate constraint on the root point!")); return; } @@ -1307,7 +1386,16 @@ void CmdSketcherConstrainDistanceY::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('DistanceY',%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,ActY); - finishDistanceConstraint(this, Obj); + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } @@ -1377,7 +1465,7 @@ void CmdSketcherConstrainParallel::activated(int iMsg) } else if (GeoId < 0) { if (hasAlreadyExternal) { - checkBothExternal(-1,-2); // just for printing the error message + showNoConstraintBetweenExternal(); return; } else @@ -1469,8 +1557,10 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) getIdsFromName(SubNames[0], Obj, GeoId1, PosId1); getIdsFromName(SubNames[1], Obj, GeoId2, PosId2); - if (checkBothExternal(GeoId1, GeoId2)) //checkBothExternal displays error message + if (checkBothExternal(GeoId1, GeoId2)){ //checkBothExternal displays error message + showNoConstraintBetweenExternal(); return; + } if (SubNames.size() == 3) { //perpendicular via point getIdsFromName(SubNames[2], Obj, GeoId3, PosId3); @@ -1740,8 +1830,10 @@ void CmdSketcherConstrainTangent::activated(int iMsg) getIdsFromName(SubNames[0], Obj, GeoId1, PosId1); getIdsFromName(SubNames[1], Obj, GeoId2, PosId2); - if (checkBothExternal(GeoId1, GeoId2)) //checkBothExternal displays error message + if (checkBothExternal(GeoId1, GeoId2)){ //checkBothExternal displays error message + showNoConstraintBetweenExternal(); return; + } if (SubNames.size() == 3) { //tangent via point getIdsFromName(SubNames[2], Obj, GeoId3, PosId3); //let's sink the point to be GeoId3. We want to keep the order the two curves have been selected in. @@ -1957,6 +2049,8 @@ void CmdSketcherConstrainRadius::activated(int iMsg) // check for which selected geometry the constraint can be applied std::vector< std::pair > geoIdRadiusMap; + std::vector< std::pair > externalGeoIdRadiusMap; + for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); ++it) { if (it->size() > 4 && it->substr(0,4) == "Edge") { int GeoId = std::atoi(it->substr(4,4000).c_str()) - 1; @@ -1972,13 +2066,74 @@ void CmdSketcherConstrainRadius::activated(int iMsg) geoIdRadiusMap.push_back(std::make_pair(GeoId, radius)); } } + if (it->size() > 4 && it->substr(0,12) == "ExternalEdge") { + int GeoId = -std::atoi(it->substr(12,4000).c_str()) - 2; + const Part::Geometry *geom = Obj->getGeometry(GeoId); + if (geom && geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + const Part::GeomArcOfCircle *arc = dynamic_cast(geom); + double radius = arc->getRadius(); + externalGeoIdRadiusMap.push_back(std::make_pair(GeoId, radius)); + } + else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { + const Part::GeomCircle *circle = dynamic_cast(geom); + double radius = circle->getRadius(); + externalGeoIdRadiusMap.push_back(std::make_pair(GeoId, radius)); + } + } } - if (geoIdRadiusMap.empty()) { + if (geoIdRadiusMap.empty() && externalGeoIdRadiusMap.empty()) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select one or more arcs or circles from the sketch.")); } - else { + + bool commitNeeded=false; + bool updateNeeded=false; + bool commandopened=false; + + if(!externalGeoIdRadiusMap.empty()) { + // Create the non-driving radius constraints now + openCommand("Add radius constraint"); + commandopened=true; + unsigned int constrSize; + + for (std::vector< std::pair >::iterator it = externalGeoIdRadiusMap.begin(); it != externalGeoIdRadiusMap.end(); ++it) { + Gui::Command::doCommand( + Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", + selection[0].getFeatName(),it->first,it->second); + + const std::vector &ConStr = Obj->Constraints.getValues(); + + constrSize=ConStr.size(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),constrSize-1,"False"); + } + + const std::vector &ConStr = Obj->Constraints.getValues(); + + std::size_t indexConstr = constrSize - externalGeoIdRadiusMap.size(); + + // Guess some reasonable distance for placing the datum text + Gui::Document *doc = getActiveGuiDocument(); + float sf = 1.f; + if (doc && doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) { + SketcherGui::ViewProviderSketch *vp = dynamic_cast(doc->getInEdit()); + sf = vp->getScaleFactor(); + + for (std::size_t i=0; iLabelDistance = 2. * sf; + } + vp->draw(); // Redraw + } + + commitNeeded=true; + updateNeeded=true; + } + + if(!geoIdRadiusMap.empty()) + { bool constrainEqual = false; if (geoIdRadiusMap.size() > 1) { int ret = QMessageBox::question(Gui::getMainWindow(), QObject::tr("Constrain equal"), @@ -1998,7 +2153,10 @@ void CmdSketcherConstrainRadius::activated(int iMsg) // Create the one radius constraint now int refGeoId = geoIdRadiusMap.front().first; double radius = geoIdRadiusMap.front().second; - openCommand("Add radius constraint"); + + if(!commandopened) + openCommand("Add radius constraint"); + Gui::Command::doCommand( Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", selection[0].getFeatName(),refGeoId,radius); @@ -2012,7 +2170,8 @@ void CmdSketcherConstrainRadius::activated(int iMsg) } else { // Create the radius constraints now - openCommand("Add radius constraint"); + if(!commandopened) + openCommand("Add radius constraint"); for (std::vector< std::pair >::iterator it = geoIdRadiusMap.begin(); it != geoIdRadiusMap.end(); ++it) { Gui::Command::doCommand( Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", @@ -2072,6 +2231,8 @@ void CmdSketcherConstrainRadius::activated(int iMsg) } commitCommand(); updateActive(); + commitNeeded=false; + updateNeeded=false; } catch (const Base::Exception& e) { QMessageBox::critical(qApp->activeWindow(), QObject::tr("Dimensional constraint"), QString::fromUtf8(e.what())); @@ -2086,11 +2247,17 @@ void CmdSketcherConstrainRadius::activated(int iMsg) else { // now dialog was shown so commit the command commitCommand(); + commitNeeded=false; } - //updateActive(); getSelection().clearSelection(); } + + if(commitNeeded) + commitCommand(); + + if(updateNeeded) + updateActive(); } bool CmdSketcherConstrainRadius::isActive(void) @@ -2159,6 +2326,8 @@ void CmdSketcherConstrainAngle::activated(int iMsg) std::swap(GeoId2,GeoId3); std::swap(PosId2,PosId3); }; + + bool bothexternal=checkBothExternal(GeoId1, GeoId2); if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { double ActAngle = 0.0; @@ -2190,15 +2359,24 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Gui::Command::doCommand( Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('AngleViaPoint',%d,%d,%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,GeoId2,GeoId3,PosId3,ActAngle); - - finishDistanceConstraint(this, Obj); + + if (bothexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; }; } else if (SubNames.size() < 3) { - if (checkBothExternal(GeoId1, GeoId2)) - return; + bool bothexternal=checkBothExternal(GeoId1, GeoId2); + if (isVertex(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) { std::swap(GeoId1,GeoId2); std::swap(PosId1,PosId2); @@ -2260,14 +2438,22 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Angle',%d,%d,%d,%d,%f)) ", selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,ActAngle); - finishDistanceConstraint(this, Obj); + if (bothexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } } else if (isEdge(GeoId1,PosId1)) { // line angle - if (GeoId1 < 0) { + if (GeoId1 < 0 && GeoId1 >= -2) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), - GeoId1 < -2 ? QObject::tr("Cannot add an angle constraint on an external geometry!") - : QObject::tr("Cannot add an angle constraint on an axis!")); + QObject::tr("Cannot add an angle constraint on an axis!")); return; } @@ -2283,7 +2469,16 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Angle',%d,%f)) ", selection[0].getFeatName(),GeoId1,ActAngle); - finishDistanceConstraint(this, Obj); + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } else if (geom->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { @@ -2298,7 +2493,16 @@ void CmdSketcherConstrainAngle::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Angle',%d,%f)) ", selection[0].getFeatName(),GeoId1,angle); - finishDistanceConstraint(this, Obj); + if (GeoId1 < -2) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + finishDistanceConstraint(this, Obj,false); + } + else + finishDistanceConstraint(this, Obj,true); + return; } } @@ -2375,7 +2579,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg) return; } else if (hasAlreadyExternal) { - checkBothExternal(-1,-2); // just for printing the error message + showNoConstraintBetweenExternal(); return; } else @@ -2642,10 +2846,10 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) std::swap(PosId2,PosId3); } + bool allexternal=false; //a bunch of validity checks if ((GeoId1 < 0 && GeoId2 < 0 && GeoId3 < 0)) { - strError = QObject::tr("Cannot add a constraint between external geometries!", dmbg); - throw(Base::Exception("")); + allexternal=true; } if (!(isVertex(GeoId1,PosId1) && !isSimpleVertex(Obj, GeoId1, PosId1) && @@ -2655,27 +2859,31 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) throw(Base::Exception("")); }; - //the essence. - //Unlike other constraints, we'll ask for a value immediately. - QDialog dlg(Gui::getMainWindow()); - Ui::InsertDatum ui_Datum; - ui_Datum.setupUi(&dlg); - dlg.setWindowTitle(EditDatumDialog::tr("Refractive index ratio", dmbg)); - ui_Datum.label->setText(EditDatumDialog::tr("Ratio n2/n1:", dmbg)); - Base::Quantity init_val; - init_val.setUnit(Base::Unit()); - init_val.setValue(0.0); + double n2divn1=0; + + if(!allexternal){ + //the essence. + //Unlike other constraints, we'll ask for a value immediately. + QDialog dlg(Gui::getMainWindow()); + Ui::InsertDatum ui_Datum; + ui_Datum.setupUi(&dlg); + dlg.setWindowTitle(EditDatumDialog::tr("Refractive index ratio", dmbg)); + ui_Datum.label->setText(EditDatumDialog::tr("Ratio n2/n1:", dmbg)); + Base::Quantity init_val; + init_val.setUnit(Base::Unit()); + init_val.setValue(0.0); - ui_Datum.labelEdit->setValue(init_val); - ui_Datum.labelEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/SketcherRefrIndexRatio")); - ui_Datum.labelEdit->setToLastUsedValue(); - ui_Datum.labelEdit->selectNumber(); + ui_Datum.labelEdit->setValue(init_val); + ui_Datum.labelEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/SketcherRefrIndexRatio")); + ui_Datum.labelEdit->setToLastUsedValue(); + ui_Datum.labelEdit->selectNumber(); - if (dlg.exec() != QDialog::Accepted) return; - ui_Datum.labelEdit->pushToHistory(); + if (dlg.exec() != QDialog::Accepted) return; + ui_Datum.labelEdit->pushToHistory(); - Base::Quantity newQuant = ui_Datum.labelEdit->value(); - double n2divn1 = newQuant.getValue(); + Base::Quantity newQuant = ui_Datum.labelEdit->value(); + n2divn1 = newQuant.getValue(); + } //add constraint openCommand("add Snell's law constraint"); @@ -2694,6 +2902,13 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('SnellsLaw',%d,%d,%d,%d,%d,%.12f)) ", selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3,n2divn1); + if (allexternal) { // it is a constraint on a external line, make it non-driving + const std::vector &ConStr = Obj->Constraints.getValues(); + + Gui::Command::doCommand(Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + selection[0].getFeatName(),ConStr.size()-1,"False"); + } + commitCommand(); updateActive(); @@ -2771,7 +2986,7 @@ void CmdSketcherConstrainInternalAlignment::activated(int iMsg) return; } else if (hasAlreadyExternal) { - checkBothExternal(-1,-2); // just for printing the error message + showNoConstraintBetweenExternal(); return; } else diff --git a/src/Mod/Sketcher/Gui/SketcherSettings.ui b/src/Mod/Sketcher/Gui/SketcherSettings.ui index 5d72e0d608..9bc8607c1b 100644 --- a/src/Mod/Sketcher/Gui/SketcherSettings.ui +++ b/src/Mod/Sketcher/Gui/SketcherSettings.ui @@ -6,8 +6,8 @@ 0 0 - 359 - 586 + 404 + 652 @@ -40,7 +40,7 @@ The color of edges being edited - + 255 255 @@ -73,7 +73,7 @@ The color of vertices being edited - + 255 255 @@ -106,7 +106,7 @@ The color of edges being edited - + 255 255 @@ -139,7 +139,7 @@ The color of vertices being edited - + 255 38 @@ -167,12 +167,32 @@ + + + + The color of fully constrained geometry in edit mode + + + + 255 + 38 + 0 + + + + ConstrainedDimColor + + + View + + + The color of construction geometry in edit mode - + 0 0 @@ -205,7 +225,7 @@ The color of external geometry in edit mode - + 204 51 @@ -233,12 +253,25 @@ + + + + + 182 + 0 + + + + Constraint color + + + The color of fully constrained geometry in edit mode - + 0 255 @@ -253,40 +286,7 @@ - - - - - 182 - 0 - - - - Constraint color - - - - - - - The color of fully constrained geometry in edit mode - - - - 255 - 38 - 0 - - - - ConstrainedIcoColor - - - View - - - - + @@ -299,27 +299,7 @@ - - - - The color of fully constrained geometry in edit mode - - - - 255 - 38 - 0 - - - - ConstrainedDimColor - - - View - - - - + @@ -332,7 +312,20 @@ - + + + + + 182 + 0 + + + + Default vertex size + + + + The default line thickness for new shapes @@ -354,8 +347,8 @@ - - + + 182 @@ -363,11 +356,11 @@ - Default vertex size + Default line width - + The default line thickness for new shapes @@ -389,8 +382,8 @@ - - + + 182 @@ -398,11 +391,28 @@ - Default line width + Cursor text color - + + + + + 0 + 0 + 255 + + + + CursorTextColor + + + View + + + + The default line thickness for new shapes @@ -424,30 +434,47 @@ - - - - - 182 - 0 - - + + - Cursor text color + Non-driving Datum color - - - + + + + The color of driving constraints in edit mode + + + + 255 + 38 + 0 + + + + ConstrainedIcoColor + + + View + + + + + + + The color of non-driving constrains or dimensions in edit mode + + 0 - 0 + 38 255 - CursorTextColor + NonDrivingConstrDimColor View diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index aad748f369..b4ff81ae2f 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -62,7 +62,6 @@ QIcon icon_ ## FUNC( Gui::BitmapFactory().pixmap(ICONSTR) ); QAction* constr_ ## FUNC = menu.addAction(icon_ ## FUNC,tr(NAMESTR), this, SLOT(FUNC()), \ QKeySequence(QString::fromUtf8(Gui::Application::Instance->commandManager().getCommandByName(CMDSTR)->getAccel()))); \ if(ACTSONSELECTION) constr_ ## FUNC->setEnabled(!items.isEmpty()); else constr_ ## FUNC->setEnabled(true); - /// Defines the member function corresponding to the CONTEXT_ITEM macro #define CONTEXT_MEMBER_DEF(CMDSTR,FUNC) \ void ConstraintView::FUNC(){ \ @@ -72,15 +71,15 @@ void ConstraintView::FUNC(){ \ class ConstraintItem : public QListWidgetItem { public: - ConstraintItem(const QIcon & icon, const QString & text,int ConstNbr,Sketcher::ConstraintType t) - : QListWidgetItem(icon,text),ConstraintNbr(ConstNbr),Type(t) + ConstraintItem(const QIcon & icon, const QString & text,int ConstNbr,Sketcher::ConstraintType t,bool isdriving=true, bool isenforceable=true) + : QListWidgetItem(icon,text),ConstraintNbr(ConstNbr),Type(t),isDriving(isdriving),isEnforceable(isenforceable) { - this->setFlags(this->flags() | Qt::ItemIsEditable); + this->setFlags(this->flags() | Qt::ItemIsEditable); } - ConstraintItem(const QString & text,int ConstNbr,Sketcher::ConstraintType t) - : QListWidgetItem(text),ConstraintNbr(ConstNbr),Type(t) + ConstraintItem(const QString & text,int ConstNbr,Sketcher::ConstraintType t,bool isdriving=true, bool isenforceable=true) + : QListWidgetItem(text),ConstraintNbr(ConstNbr),Type(t),isDriving(isdriving),isEnforceable(isenforceable) { - this->setFlags(this->flags() | Qt::ItemIsEditable); + this->setFlags(this->flags() | Qt::ItemIsEditable); } ~ConstraintItem() { @@ -106,9 +105,12 @@ public: int ConstraintNbr; Sketcher::ConstraintType Type; + bool isDriving; + bool isEnforceable; private: QVariant quantity; + }; ConstraintView::ConstraintView(QWidget *parent) @@ -129,11 +131,32 @@ void ConstraintView::contextMenuEvent (QContextMenuEvent* event) CONTEXT_ITEM("Sketcher_SelectElementsAssociatedWithConstraints","Select Elements","Sketcher_SelectElementsAssociatedWithConstraints",doSelectConstraints,true) menu.addSeparator(); + + if(item) // Non-driving-constraints/measurements + { + ConstraintItem *it = dynamic_cast(item); + + QAction* driven = menu.addAction(it->isDriving?tr("Disable"):tr("Enable"), this, SLOT(updateDrivingStatus())); + // if its the right constraint + if ((it->Type == Sketcher::Distance || + it->Type == Sketcher::DistanceX || + it->Type == Sketcher::DistanceY || + it->Type == Sketcher::Radius || + it->Type == Sketcher::Angle || + it->Type == Sketcher::SnellsLaw) && it->isEnforceable) { - QAction* change = menu.addAction(tr("Change value"), this, SLOT(modifyCurrentItem())); - QVariant v = item ? item->data(Qt::UserRole) : QVariant(); - change->setEnabled(v.isValid()); + driven->setEnabled(true); + } + else{ + driven->setEnabled(false); + } + + QAction* change = menu.addAction(tr("Change value"), this, SLOT(modifyCurrentItem())); + QVariant v = item ? item->data(Qt::UserRole) : QVariant(); + change->setEnabled(v.isValid() && it->isDriving); + + } QAction* rename = menu.addAction(tr("Rename"), this, SLOT(renameCurrentItem()) #ifndef Q_WS_MAC // on Mac F2 doesn't seem to trigger an edit signal ,QKeySequence(Qt::Key_F2) @@ -149,6 +172,17 @@ void ConstraintView::contextMenuEvent (QContextMenuEvent* event) CONTEXT_MEMBER_DEF("Sketcher_SelectElementsAssociatedWithConstraints",doSelectConstraints) +void ConstraintView::updateDrivingStatus() +{ + QListWidgetItem* item = currentItem(); + + if (item){ + ConstraintItem *it = dynamic_cast(item); + + onUpdateDrivingStatus(item, !it->isDriving); + } +} + void ConstraintView::modifyCurrentItem() { /*emit*/itemActivated(currentItem()); @@ -208,6 +242,10 @@ TaskSketcherConstrains::TaskSketcherConstrains(ViewProviderSketch *sketchView) ui->listWidgetConstraints, SIGNAL(itemChanged(QListWidgetItem *)), this , SLOT (on_listWidgetConstraints_itemChanged(QListWidgetItem *)) ); + QObject::connect( + ui->listWidgetConstraints, SIGNAL(onUpdateDrivingStatus(QListWidgetItem *, bool)), + this , SLOT (on_listWidgetConstraints_updateDrivingStatus(QListWidgetItem *, bool)) + ); connectionConstraintsChanged = sketchView->signalConstraintsChanged.connect( boost::bind(&SketcherGui::TaskSketcherConstrains::slotConstraintsChanged, this)); @@ -293,12 +331,12 @@ void TaskSketcherConstrains::on_listWidgetConstraints_itemActivated(QListWidgetI if (!item) return; // if its the right constraint - if (it->Type == Sketcher::Distance || + if ((it->Type == Sketcher::Distance || it->Type == Sketcher::DistanceX || it->Type == Sketcher::DistanceY || it->Type == Sketcher::Radius || it->Type == Sketcher::Angle || - it->Type == Sketcher::SnellsLaw) { + it->Type == Sketcher::SnellsLaw) && it->isDriving) { EditDatumDialog *editDatumDialog = new EditDatumDialog(this->sketchView, it->ConstraintNbr); editDatumDialog->exec(false); @@ -306,6 +344,30 @@ void TaskSketcherConstrains::on_listWidgetConstraints_itemActivated(QListWidgetI } } +void TaskSketcherConstrains::on_listWidgetConstraints_updateDrivingStatus(QListWidgetItem *item, bool status) +{ + ConstraintItem *it = dynamic_cast(item); + if (!item) return; + + const std::vector< Sketcher::Constraint * > &vals = sketchView->getSketchObject()->Constraints.getValues(); + + try { + Gui::Command::openCommand("Modify driving status of constraint"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.setDriving(%i,%s)", + this->sketchView->getSketchObject()->getNameInDocument(), + it->ConstraintNbr, + status?"True":"False"); + Gui::Command::commitCommand(); + Gui::Command::updateActive(); + } + catch (const Base::Exception& e) { + Gui::Command::abortCommand(); + } + + slotConstraintsChanged(); + +} + void TaskSketcherConstrains::on_listWidgetConstraints_itemChanged(QListWidgetItem *item) { if (!item || inEditMode) @@ -381,6 +443,13 @@ void TaskSketcherConstrains::slotConstraintsChanged(void) QIcon iaellipsefocus1 ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_Focus1") ); QIcon iaellipsefocus2 ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment_Ellipse_Focus2") ); QIcon iaellipseother ( Gui::BitmapFactory().pixmap("Constraint_InternalAlignment") ); + + QIcon hdist_driven ( Gui::BitmapFactory().pixmap("Constraint_HorizontalDistance_Driven") ); + QIcon vdist_driven( Gui::BitmapFactory().pixmap("Constraint_VerticalDistance_Driven") ); + QIcon dist_driven ( Gui::BitmapFactory().pixmap("Constraint_Length_Driven") ); + QIcon radi_driven ( Gui::BitmapFactory().pixmap("Constraint_Radius_Driven") ); + QIcon angl_driven ( Gui::BitmapFactory().pixmap("Constraint_InternalAngle_Driven") ); + QIcon snell_driven ( Gui::BitmapFactory().pixmap("Constraint_SnellsLaw_Driven") ); assert(sketchView); // Build up ListView with the constraints @@ -403,6 +472,7 @@ void TaskSketcherConstrains::slotConstraintsChanged(void) 1 <=> Normal 2 <=> Datums 3 <=> Named + 4 <=> Non-Driving */ switch((*it)->Type){ case Sketcher::Horizontal: @@ -442,48 +512,48 @@ void TaskSketcherConstrains::slotConstraintsChanged(void) ui->listWidgetConstraints->addItem(new ConstraintItem(symm,name,i-1,(*it)->Type)); break; case Sketcher::Distance: - if (Filter<3 || !(*it)->Name.empty()) { - ConstraintItem* item = new ConstraintItem(dist,name,i-1,(*it)->Type); + if (((Filter<3 || !(*it)->Name.empty())) || (Filter==4 && !(*it)->isDriving)) { + ConstraintItem* item = new ConstraintItem((*it)->isDriving?dist:dist_driven,name,i-1,(*it)->Type,(*it)->isDriving, ((*it)->First>=0 || (*it)->Second>=0 || (*it)->Third>=0)); name = QString::fromLatin1("%1 (%2)").arg(name).arg(Base::Quantity((*it)->Value,Base::Unit::Length).getUserString()); - item->setData(Qt::UserRole, name); + item->setData(Qt::UserRole, name); ui->listWidgetConstraints->addItem(item); } break; case Sketcher::DistanceX: - if (Filter<3 || !(*it)->Name.empty()) { - ConstraintItem* item = new ConstraintItem(hdist,name,i-1,(*it)->Type); + if (((Filter<3 || !(*it)->Name.empty())) || (Filter==4 && !(*it)->isDriving)) { + ConstraintItem* item = new ConstraintItem((*it)->isDriving?hdist:hdist_driven,name,i-1,(*it)->Type,(*it)->isDriving, ((*it)->First>=0 || (*it)->Second>=0 || (*it)->Third>=0)); name = QString::fromLatin1("%1 (%2)").arg(name).arg(Base::Quantity(std::abs((*it)->Value),Base::Unit::Length).getUserString()); item->setData(Qt::UserRole, name); ui->listWidgetConstraints->addItem(item); } break; case Sketcher::DistanceY: - if (Filter<3 || !(*it)->Name.empty()) { - ConstraintItem* item = new ConstraintItem(vdist,name,i-1,(*it)->Type); + if (((Filter<3 || !(*it)->Name.empty())) || (Filter==4 && !(*it)->isDriving)) { + ConstraintItem* item = new ConstraintItem((*it)->isDriving?vdist:vdist_driven,name,i-1,(*it)->Type,(*it)->isDriving, ((*it)->First>=0 || (*it)->Second>=0 || (*it)->Third>=0)); name = QString::fromLatin1("%1 (%2)").arg(name).arg(Base::Quantity(std::abs((*it)->Value),Base::Unit::Length).getUserString()); item->setData(Qt::UserRole, name); ui->listWidgetConstraints->addItem(item); } break; case Sketcher::Radius: - if (Filter<3 || !(*it)->Name.empty()) { - ConstraintItem* item = new ConstraintItem(radi,name,i-1,(*it)->Type); + if (((Filter<3 || !(*it)->Name.empty())) || (Filter==4 && !(*it)->isDriving)) { + ConstraintItem* item = new ConstraintItem((*it)->isDriving?radi:radi_driven,name,i-1,(*it)->Type,(*it)->isDriving, ((*it)->First>=0 || (*it)->Second>=0 || (*it)->Third>=0)); name = QString::fromLatin1("%1 (%2)").arg(name).arg(Base::Quantity((*it)->Value,Base::Unit::Length).getUserString()); item->setData(Qt::UserRole, name); ui->listWidgetConstraints->addItem(item); } break; case Sketcher::Angle: - if (Filter<3 || !(*it)->Name.empty()) { - ConstraintItem* item = new ConstraintItem(angl,name,i-1,(*it)->Type); + if (((Filter<3 || !(*it)->Name.empty())) || (Filter==4 && !(*it)->isDriving)) { + ConstraintItem* item = new ConstraintItem((*it)->isDriving?angl:angl_driven,name,i-1,(*it)->Type,(*it)->isDriving, ((*it)->First>=0 || (*it)->Second>=0 || (*it)->Third>=0)); name = QString::fromLatin1("%1 (%2)").arg(name).arg(Base::Quantity(Base::toDegrees(std::abs((*it)->Value)),Base::Unit::Angle).getUserString()); item->setData(Qt::UserRole, name); ui->listWidgetConstraints->addItem(item); } break; case Sketcher::SnellsLaw: - if (Filter<3 || !(*it)->Name.empty()) { - ConstraintItem* item = new ConstraintItem(snell,name,i-1,(*it)->Type); + if (((Filter<3 || !(*it)->Name.empty())) || (Filter==4 && !(*it)->isDriving)) { + ConstraintItem* item = new ConstraintItem((*it)->isDriving?snell:snell_driven,name,i-1,(*it)->Type,(*it)->isDriving, ((*it)->First>=0 || (*it)->Second>=0 || (*it)->Third>=0)); double v = (*it)->Value; double n1 = 1.0; diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h index 7d78060007..18eec1786e 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.h @@ -48,11 +48,15 @@ public: protected: void contextMenuEvent (QContextMenuEvent* event); +Q_SIGNALS: + void onUpdateDrivingStatus(QListWidgetItem *item, bool status); + protected Q_SLOTS: void modifyCurrentItem(); void renameCurrentItem(); void deleteSelectedItems(); void doSelectConstraints(); + void updateDrivingStatus(); }; class TaskSketcherConstrains : public Gui::TaskView::TaskBox, public Gui::SelectionObserver @@ -74,6 +78,7 @@ public Q_SLOTS: void on_listWidgetConstraints_itemSelectionChanged(void); void on_listWidgetConstraints_itemActivated(QListWidgetItem *item); void on_listWidgetConstraints_itemChanged(QListWidgetItem * item); + void on_listWidgetConstraints_updateDrivingStatus(QListWidgetItem *item, bool status); protected: void changeEvent(QEvent *e); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui index cb56a02609..3e3ba1f9e6 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.ui @@ -6,7 +6,7 @@ 0 0 - 176 + 212 288 @@ -26,7 +26,7 @@ - 1 + 0 @@ -48,6 +48,11 @@ Named + + + Non-Driving + + diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index fee2b6431d..3303ee392f 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -117,18 +117,19 @@ using namespace SketcherGui; using namespace Sketcher; -SbColor ViewProviderSketch::VertexColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0) -SbColor ViewProviderSketch::CurveColor (1.0f,1.0f,1.0f); // #FFFFFF -> (255,255,255) -SbColor ViewProviderSketch::CurveDraftColor (0.0f,0.0f,0.86f); // #0000DC -> ( 0, 0,220) -SbColor ViewProviderSketch::CurveExternalColor (0.8f,0.2f,0.6f); // #CC3399 -> (204, 51,153) -SbColor ViewProviderSketch::CrossColorH (0.8f,0.4f,0.4f); // #CC6666 -> (204,102,102) -SbColor ViewProviderSketch::CrossColorV (0.4f,0.8f,0.4f); // #66CC66 -> (102,204,102) -SbColor ViewProviderSketch::FullyConstrainedColor (0.0f,1.0f,0.0f); // #00FF00 -> ( 0,255, 0) -SbColor ViewProviderSketch::ConstrDimColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0) -SbColor ViewProviderSketch::ConstrIcoColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0) -SbColor ViewProviderSketch::PreselectColor (0.88f,0.88f,0.0f); // #E1E100 -> (225,225, 0) -SbColor ViewProviderSketch::SelectColor (0.11f,0.68f,0.11f); // #1CAD1C -> ( 28,173, 28) -SbColor ViewProviderSketch::PreselectSelectedColor(0.36f,0.48f,0.11f); // #5D7B1C -> ( 93,123, 28) +SbColor ViewProviderSketch::VertexColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0) +SbColor ViewProviderSketch::CurveColor (1.0f,1.0f,1.0f); // #FFFFFF -> (255,255,255) +SbColor ViewProviderSketch::CurveDraftColor (0.0f,0.0f,0.86f); // #0000DC -> ( 0, 0,220) +SbColor ViewProviderSketch::CurveExternalColor (0.8f,0.2f,0.6f); // #CC3399 -> (204, 51,153) +SbColor ViewProviderSketch::CrossColorH (0.8f,0.4f,0.4f); // #CC6666 -> (204,102,102) +SbColor ViewProviderSketch::CrossColorV (0.4f,0.8f,0.4f); // #66CC66 -> (102,204,102) +SbColor ViewProviderSketch::FullyConstrainedColor (0.0f,1.0f,0.0f); // #00FF00 -> ( 0,255, 0) +SbColor ViewProviderSketch::ConstrDimColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0) +SbColor ViewProviderSketch::ConstrIcoColor (1.0f,0.149f,0.0f); // #FF2600 -> (255, 38, 0) +SbColor ViewProviderSketch::NonDrivingConstrDimColor (0.0f,0.149f,1.0f); // #0026FF -> ( 0, 38,255) +SbColor ViewProviderSketch::PreselectColor (0.88f,0.88f,0.0f); // #E1E100 -> (225,225, 0) +SbColor ViewProviderSketch::SelectColor (0.11f,0.68f,0.11f); // #1CAD1C -> ( 28,173, 28) +SbColor ViewProviderSketch::PreselectSelectedColor (0.36f,0.48f,0.11f); // #5D7B1C -> ( 93,123, 28) // Variables for holding previous click SbTime ViewProviderSketch::prvClickTime; SbVec3f ViewProviderSketch::prvClickPoint; @@ -2302,9 +2303,9 @@ void ViewProviderSketch::updateColor(void) else { if (hasDatumLabel) { SoDatumLabel *l = dynamic_cast(s->getChild(CONSTRAINT_SEPARATOR_INDEX_MATERIAL_OR_DATUMLABEL)); - l->textColor = ConstrDimColor; + l->textColor = constraint->isDriving?ConstrDimColor:NonDrivingConstrDimColor; } else if (hasMaterial) { - m->diffuseColor = ConstrDimColor; + m->diffuseColor = constraint->isDriving?ConstrDimColor:NonDrivingConstrDimColor; } } } @@ -2383,6 +2384,9 @@ QColor ViewProviderSketch::constrColor(int constraintId) static QColor constrIcoColor((int)(ConstrIcoColor [0] * 255.0f), (int)(ConstrIcoColor[1] * 255.0f), (int)(ConstrIcoColor[2] * 255.0f)); + static QColor nonDrivingConstrIcoColor((int)(NonDrivingConstrDimColor[0] * 255.0f), + (int)(NonDrivingConstrDimColor[1] * 255.0f), + (int)(NonDrivingConstrDimColor[2] * 255.0f)); static QColor constrIconSelColor ((int)(SelectColor[0] * 255.0f), (int)(SelectColor[1] * 255.0f), (int)(SelectColor[2] * 255.0f)); @@ -2390,12 +2394,17 @@ QColor ViewProviderSketch::constrColor(int constraintId) (int)(PreselectColor[1] * 255.0f), (int)(PreselectColor[2] * 255.0f)); + const std::vector &constraints = getSketchObject()->Constraints.getValues(); + if (edit->PreselectConstraintSet.count(constraintId)) return constrIconPreselColor; else if (edit->SelConstraintSet.find(constraintId) != edit->SelConstraintSet.end()) return constrIconSelColor; + else if(!constraints[constraintId]->isDriving) + return nonDrivingConstrIcoColor; else return constrIcoColor; + } int ViewProviderSketch::constrColorPriority(int constraintId) @@ -3872,7 +3881,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) // every constrained visual node gets its own material for preselection and selection SoMaterial *mat = new SoMaterial; mat->ref(); - mat->diffuseColor = ConstrDimColor; + mat->diffuseColor = (*it)->isDriving?ConstrDimColor:NonDrivingConstrDimColor; // Get sketch normal Base::Vector3d RN(0,0,1); @@ -3895,7 +3904,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) SoDatumLabel *text = new SoDatumLabel(); text->norm.setValue(norm); text->string = ""; - text->textColor = ConstrDimColor; + text->textColor = (*it)->isDriving?ConstrDimColor:NonDrivingConstrDimColor;; text->size.setValue(fontSize); text->useAntialiasing = false; SoAnnotation *anno = new SoAnnotation(); @@ -4145,6 +4154,10 @@ bool ViewProviderSketch::setEdit(int ModNum) color = (unsigned long)(ConstrIcoColor.getPackedValue()); color = hGrp->GetUnsigned("ConstrainedIcoColor", color); ConstrIcoColor.setPackedValue((uint32_t)color, transparency); + // set non-driving constraint color + color = (unsigned long)(NonDrivingConstrDimColor.getPackedValue()); + color = hGrp->GetUnsigned("NonDrivingConstrDimColor", color); + NonDrivingConstrDimColor.setPackedValue((uint32_t)color, transparency); // set the external geometry color color = (unsigned long)(CurveExternalColor.getPackedValue()); color = hGrp->GetUnsigned("ExternalColor", color); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index 7761d98d9f..ac30c83eca 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -349,6 +349,7 @@ protected: static SbColor FullyConstrainedColor; static SbColor ConstrDimColor; static SbColor ConstrIcoColor; + static SbColor NonDrivingConstrDimColor; static SbColor PreselectColor; static SbColor SelectColor; static SbColor PreselectSelectedColor;