diff --git a/src/Mod/Sketcher/App/Constraint.cpp b/src/Mod/Sketcher/App/Constraint.cpp index 20c1b28dca..1b00d25061 100644 --- a/src/Mod/Sketcher/App/Constraint.cpp +++ b/src/Mod/Sketcher/App/Constraint.cpp @@ -126,6 +126,7 @@ Quantity Constraint::getPresentationValue() const quantity.setUnit(Unit::Angle); break; case SnellsLaw: + case Weight: quantity.setValue(Value); break; default: diff --git a/src/Mod/Sketcher/App/Constraint.h b/src/Mod/Sketcher/App/Constraint.h index b8ee2a2ac3..7a3316b08a 100644 --- a/src/Mod/Sketcher/App/Constraint.h +++ b/src/Mod/Sketcher/App/Constraint.h @@ -57,6 +57,7 @@ enum ConstraintType { SnellsLaw = 16, Block = 17, Diameter = 18, + Weight = 19, NumConstraintTypes // must be the last item! }; @@ -117,7 +118,7 @@ public: inline bool isDimensional() const { return Type == Distance || Type == DistanceX || Type == DistanceY || - Type == Radius || Type == Diameter || Type == Angle || Type == SnellsLaw; + Type == Radius || Type == Diameter || Type == Angle || Type == SnellsLaw || Type == Weight; } friend class PropertyConstraintList; diff --git a/src/Mod/Sketcher/App/ConstraintPyImp.cpp b/src/Mod/Sketcher/App/ConstraintPyImp.cpp index 03204f4aca..cafa0019e0 100644 --- a/src/Mod/Sketcher/App/ConstraintPyImp.cpp +++ b/src/Mod/Sketcher/App/ConstraintPyImp.cpp @@ -169,6 +169,13 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/) this->getConstraintPtr()->LabelPosition = 10; valid = true; } + else if (strcmp("Weight",ConstraintType) == 0) { + this->getConstraintPtr()->Type = Weight; + // set a value that is out of range of result of atan2 + // this value is handled in ViewProviderSketch + this->getConstraintPtr()->LabelPosition = 10; + valid = true; + } if (valid) { this->getConstraintPtr()->First = FirstIndex; this->getConstraintPtr()->setValue(Value); @@ -503,6 +510,7 @@ std::string ConstraintPy::representation(void) const case Block : result << "'Block' (" << getConstraintPtr()->First << ")>";break; case Radius : result << "'Radius'>";break; case Diameter : result << "'Diameter'>";break; + case Weight : result << "'Weight'>";break; case Parallel : result << "'Parallel'>";break; case Tangent : if (this->getConstraintPtr()->Third == Constraint::GeoUndef) @@ -554,6 +562,7 @@ Py::String ConstraintPy::getType(void) const case Block : return Py::String("Block");break; case Radius : return Py::String("Radius");break; case Diameter : return Py::String("Diameter");break; + case Weight : return Py::String("Weight");break; case Parallel : return Py::String("Parallel");break; case Tangent : return Py::String("Tangent");break; case Perpendicular : return Py::String("Perpendicular");break; diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index cb22c78d9e..bb5b7d18a4 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -1406,6 +1406,19 @@ int Sketch::addConstraint(const Constraint *constraint) rtn = addDiameterConstraint(constraint->First, c.value,c.driving); break; } + case Weight: + { + c.value = new double(constraint->getValue()); + if(c.driving) + FixParameters.push_back(c.value); + else { + Parameters.push_back(c.value); + DrivenParameters.push_back(c.value); + } + + rtn = addRadiusConstraint(constraint->First, c.value,c.driving); + break; + } case Equal: rtn = addEqualConstraint(constraint->First,constraint->Second); break; diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 448e618b76..33e18229ac 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -327,7 +327,7 @@ int SketchObject::setDatum(int ConstrId, double Datum) type != Perpendicular) return -1; - if ((type == Distance || type == Radius || type == Diameter) && Datum <= 0) + if ((type == Distance || type == Radius || type == Diameter || type == Weight) && Datum <= 0) return (Datum == 0) ? -5 : -4; // copy the list @@ -1243,6 +1243,9 @@ void SketchObject::addGeometryState(const Constraint* cstr) const { auto gf = GeometryFacade::getFacade(vals[cstr->First]); gf->setInternalType(InternalType::BSplineControlPoint); + + // handle constraint as adimensional + break; } case BSplineKnotPoint: @@ -3839,6 +3842,7 @@ int SketchObject::addSymmetric(const std::vector &geoIdList, int refGeoId, (*it)->Type == Sketcher::Equal || (*it)->Type == Sketcher::Radius || (*it)->Type == Sketcher::Diameter || + (*it)->Type == Sketcher::Weight || (*it)->Type == Sketcher::Angle || (*it)->Type == Sketcher::PointOnObject ){ Constraint *constNew = (*it)->copy(); @@ -4133,9 +4137,10 @@ int SketchObject::addCopy(const std::vector &geoIdList, const Base::Vector3 if( ((*it)->Type != Sketcher::DistanceX && (*it)->Type != Sketcher::DistanceY ) || (*it)->FirstPos == Sketcher::none ) { // if it is not a point locking DistanceX/Y if (((*it)->Type == Sketcher::DistanceX || - (*it)->Type == Sketcher::DistanceY || - (*it)->Type == Sketcher::Distance || - (*it)->Type == Sketcher::Diameter || + (*it)->Type == Sketcher::DistanceY || + (*it)->Type == Sketcher::Distance || + (*it)->Type == Sketcher::Diameter || + (*it)->Type == Sketcher::Weight || (*it)->Type == Sketcher::Radius ) && clone ) { // Distances on a single Element are mapped to equality constraints in clone mode Constraint *constNew = (*it)->copy(); @@ -4831,12 +4836,9 @@ int SketchObject::exposeInternalGeometry(int GeoId) // search for first pole weight constraint for (std::vector< Sketcher::Constraint * >::const_iterator it= vals.begin(); it != vals.end(); ++it) { - if((*it)->Type == Sketcher::Radius && (*it)->First == controlpointgeoids[0]) { + if((*it)->Type == Sketcher::Weight && (*it)->First == controlpointgeoids[0]) { isfirstweightconstrained = true ; } - else if((*it)->Type == Sketcher::Diameter && (*it)->First == controlpointgeoids[0]) { - isfirstweightconstrained = true ; - } } } @@ -5218,8 +5220,8 @@ int SketchObject::deleteUnusedInternalGeometry(int GeoId, bool delgeoid) } } - // ignore radii and diameters - else if (((*itc)->Type!=Sketcher::Radius && (*itc)->Type!=Sketcher::Diameter) && ( (*itc)->Second == (*it) || (*itc)->First == (*it) || (*itc)->Third == (*it)) ) { + // ignore weight constraints + else if (((*itc)->Type!=Sketcher::Weight) && ( (*itc)->Second == (*it) || (*itc)->First == (*it) || (*itc)->Third == (*it)) ) { (*ita)++; } } @@ -5756,6 +5758,7 @@ int SketchObject::carbonCopy(App::DocumentObject * pObj, bool construction) if ((*it)->Type == Sketcher::Distance || (*it)->Type == Sketcher::Radius || (*it)->Type == Sketcher::Diameter || + (*it)->Type == Sketcher::Weight || (*it)->Type == Sketcher::Angle || (*it)->Type == Sketcher::SnellsLaw || (*it)->Type == Sketcher::DistanceX || @@ -7067,6 +7070,7 @@ bool SketchObject::evaluateConstraint(const Constraint *constraint) const switch (constraint->Type) { case Radius: case Diameter: + case Weight: case Horizontal: case Vertical: case Distance: @@ -7487,16 +7491,39 @@ void SketchObject::restoreFinished() void SketchObject::migrateSketch(void) { - bool updateGeoState = false; + bool noextensions = false; for( const auto & g : getInternalGeometry() ) if(!g->hasExtension(SketchGeometryExtension::getClassTypeId())) // no extension - legacy file - updateGeoState = true; + noextensions = true; - if(updateGeoState) { + if(noextensions) { for( auto c : Constraints.getValues()) { addGeometryState(c); + + // Convert B-Spline controlpoints radius/diameter constraints to Weight cosntraints + if(c->Type == InternalAlignment && c->AlignmentType == BSplineControlPoint) { + int circlegeoid = c->First; + int bsplinegeoid = c->Second; + + auto bsp = static_cast(getGeometry(bsplinegeoid)); + + std::vector weights = bsp->getWeights(); + + for( auto ccp : Constraints.getValues()) { + + if( (ccp->Type == Radius || ccp->Type == Diameter ) && + ccp->First == circlegeoid ) { + + if(c->InternalAlignmentIndex < int(weights.size())) { + ccp->Type = Weight; + ccp->setValue(weights[c->InternalAlignmentIndex]); + + } + } + } + } } } } @@ -7912,9 +7939,6 @@ int SketchObject::getGeometryId(int GeoId, long &id) const return 0; } - - - // Python Sketcher feature --------------------------------------------------------- namespace App { diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.cpp b/src/Mod/Sketcher/Gui/CommandConstraints.cpp index 2dab96b05b..202b1d6068 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.cpp +++ b/src/Mod/Sketcher/Gui/CommandConstraints.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "ViewProviderSketch.h" #include "DrawSketchHandler.h" @@ -255,6 +256,20 @@ bool SketcherGui::IsPointAlreadyOnCurve(int GeoIdCurve, int GeoIdPoint, Sketcher return Obj->isPointOnCurve(GeoIdCurve, p.x, p.y); } +bool SketcherGui::isBsplinePole(const Part::Geometry * geo) +{ + auto gf = GeometryFacade::getFacade(geo); + + return gf->getInternalType() == InternalType::BSplineControlPoint; +} + +bool SketcherGui::isBsplinePole(const Sketcher::SketchObject* Obj, int GeoId) +{ + auto geom = Obj->getGeometry(GeoId); + + return isBsplinePole(geom); +} + bool SketcherGui::ReleaseHandler(Gui::Document* doc) { if (doc) { if (doc->getInEdit() && doc->getInEdit()->isDerivedFrom(SketcherGui::ViewProviderSketch::getClassTypeId())) { @@ -2655,6 +2670,14 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg) continue; } + if( geom && isBsplinePole(geom)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + abortCommand(); + + continue; + } + cnt++; Gui::cmdAppObjectArgs(selection[0].getObject(),"addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ", points[iPnt].GeoId, points[iPnt].PosId, curves[iCrv].GeoId); @@ -2668,9 +2691,10 @@ void CmdSketcherConstrainPointOnObject::activated(int iMsg) QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("None of the selected points were constrained " "onto the respective curves, " - "either because they are parts " + "because they are parts " "of the same element, " - "or because they are both external geometry.")); + "because they are both external geometry, " + "or because the edge is not eligible.")); } return; } @@ -2730,6 +2754,14 @@ void CmdSketcherConstrainPointOnObject::applyConstraint(std::vector & return; } + if( geom && isBsplinePole(geom)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + abortCommand(); + + return; + } + if (allOK) { Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('PointOnObject',%d,%d,%d)) ", GeoIdVt, PosIdVt, GeoIdCrv); @@ -3508,6 +3540,12 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + openCommand(QT_TRANSLATE_NOOP("Command", "Add perpendicular constraint")); try{ @@ -3607,6 +3645,12 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) return; } + if(isBsplinePole(geom2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + openCommand(QT_TRANSLATE_NOOP("Command", "Add perpendicularity constraint")); Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Perpendicular',%d,%d,%d)) ", GeoId1,PosId1,GeoId2); @@ -3643,6 +3687,12 @@ void CmdSketcherConstrainPerpendicular::activated(int iMsg) if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId()) std::swap(GeoId1,GeoId2); + if(isBsplinePole(Obj, GeoId1)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + // GeoId2 is the line geo1 = Obj->getGeometry(GeoId1); geo2 = Obj->getGeometry(GeoId2); @@ -3818,6 +3868,12 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector & if (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId()) std::swap(GeoId1,GeoId2); + if(isBsplinePole(Obj, GeoId1)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + // GeoId2 is the line geo1 = Obj->getGeometry(GeoId1); geo2 = Obj->getGeometry(GeoId2); @@ -3963,6 +4019,12 @@ void CmdSketcherConstrainPerpendicular::applyConstraint(std::vector & if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + openCommand(QT_TRANSLATE_NOOP("Command", "Add perpendicular constraint")); try{ @@ -4112,6 +4174,12 @@ void CmdSketcherConstrainTangent::activated(int iMsg) if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + openCommand(QT_TRANSLATE_NOOP("Command", "Add tangent constraint")); try{ @@ -4194,6 +4262,12 @@ void CmdSketcherConstrainTangent::activated(int iMsg) return; } + if(isBsplinePole(geom2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + openCommand(QT_TRANSLATE_NOOP("Command", "Add tangent constraint")); Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Tangent',%d,%d,%d)) ", GeoId1,PosId1,GeoId2); @@ -4218,6 +4292,11 @@ void CmdSketcherConstrainTangent::activated(int iMsg) return; } + if(isBsplinePole(geom1) || isBsplinePole(geom2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } // check if there is a coincidence constraint on GeoId1, GeoId2 const std::vector< Constraint * > &cvals = Obj->Constraints.getValues(); @@ -4437,6 +4516,12 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector &selSeq return; } + if(isBsplinePole(geom1) || isBsplinePole(geom2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + if( geom1 && geom2 && ( geom1->getTypeId() == Part::GeomEllipse::getClassTypeId() || @@ -4606,6 +4691,12 @@ void CmdSketcherConstrainTangent::applyConstraint(std::vector &selSeq if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + openCommand(QT_TRANSLATE_NOOP("Command", "Add tangent constraint")); try{ @@ -4667,8 +4758,8 @@ CmdSketcherConstrainRadius::CmdSketcherConstrainRadius() { sAppModule = "Sketcher"; sGroup = QT_TR_NOOP("Sketcher"); - sMenuText = QT_TR_NOOP("Constrain radius"); - sToolTipText = QT_TR_NOOP("Fix the radius of a circle or an arc"); + sMenuText = QT_TR_NOOP("Constrain radius or weight"); + sToolTipText = QT_TR_NOOP("Fix the radius of a circle or an arc or fix the weight of a pole of a B-Spline"); sWhatsThis = "Sketcher_ConstrainRadius"; sStatusTip = sToolTipText; sPixmap = "Constraint_Radius"; @@ -4715,6 +4806,9 @@ void CmdSketcherConstrainRadius::activated(int iMsg) std::vector< std::pair > geoIdRadiusMap; std::vector< std::pair > externalGeoIdRadiusMap; + bool poles = false; + bool nonpoles = false; + for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); ++it) { bool issegmentfixed = false; int GeoId; @@ -4742,6 +4836,8 @@ void CmdSketcherConstrainRadius::activated(int iMsg) else { geoIdRadiusMap.push_back(std::make_pair(GeoId, radius)); } + + nonpoles = true; } else if (geom && geom->getTypeId() == Part::GeomCircle::getClassTypeId()) { const Part::GeomCircle *circle = static_cast(geom); @@ -4753,6 +4849,11 @@ void CmdSketcherConstrainRadius::activated(int iMsg) else { geoIdRadiusMap.push_back(std::make_pair(GeoId, radius)); } + + if(isBsplinePole(geom)) + poles = true; + else + nonpoles = true; } } @@ -4761,6 +4862,12 @@ void CmdSketcherConstrainRadius::activated(int iMsg) QObject::tr("Select one or more arcs or circles from the sketch.")); } + if(poles && nonpoles) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select either only one or more B-Spline poles or only one or more arcs or circles from the sketch, but not mixed.")); + return; + } + bool commitNeeded=false; bool updateNeeded=false; bool commandopened=false; @@ -4772,8 +4879,13 @@ void CmdSketcherConstrainRadius::activated(int iMsg) unsigned int constrSize = 0; for (std::vector< std::pair >::iterator it = externalGeoIdRadiusMap.begin(); it != externalGeoIdRadiusMap.end(); ++it) { - Gui::cmdAppObjectArgs(selection[0].getObject(),"addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", - it->first,it->second); + + if(nonpoles) + Gui::cmdAppObjectArgs(selection[0].getObject(),"addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", + it->first,it->second); + else + Gui::cmdAppObjectArgs(selection[0].getObject(),"addConstraint(Sketcher.Constraint('Weight',%d,%f)) ", + it->first,it->second); const std::vector &ConStr = Obj->Constraints.getValues(); @@ -4829,8 +4941,12 @@ void CmdSketcherConstrainRadius::activated(int iMsg) if(!commandopened) openCommand(QT_TRANSLATE_NOOP("Command", "Add radius constraint")); - Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", - refGeoId,radius); + if(nonpoles) + Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", + refGeoId,radius); + else + Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Weight',%d,%f)) ", + refGeoId,radius); // Add the equality constraints for (std::vector< std::pair >::iterator it = geoIdRadiusMap.begin()+1; it != geoIdRadiusMap.end(); ++it) { @@ -4844,8 +4960,12 @@ void CmdSketcherConstrainRadius::activated(int iMsg) if(!commandopened) openCommand(QT_TRANSLATE_NOOP("Command", "Add radius constraint")); for (std::vector< std::pair >::iterator it = geoIdRadiusMap.begin(); it != geoIdRadiusMap.end(); ++it) { - Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", - it->first,it->second); + if(nonpoles) + Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", + it->first,it->second); + else + Gui::cmdAppObjectArgs(selection[0].getObject(), "addConstraint(Sketcher.Constraint('Weight',%d,%f)) ", + it->first,it->second); if (constraintCreationMode==Reference) { const std::vector &ConStr = Obj->Constraints.getValues(); @@ -4878,12 +4998,20 @@ void CmdSketcherConstrainRadius::activated(int iMsg) QDialog dlg(Gui::getMainWindow()); Ui::InsertDatum ui_Datum; ui_Datum.setupUi(&dlg); - dlg.setWindowTitle(EditDatumDialog::tr("Change radius")); - ui_Datum.label->setText(EditDatumDialog::tr("Radius:")); Base::Quantity init_val; - init_val.setUnit(Base::Unit::Length); init_val.setValue(geoIdRadiusMap.front().second); + if(poles) { + dlg.setWindowTitle(EditDatumDialog::tr("Change weight")); + ui_Datum.label->setText(EditDatumDialog::tr("Weight:")); + + } + else{ + dlg.setWindowTitle(EditDatumDialog::tr("Change radius")); + ui_Datum.label->setText(EditDatumDialog::tr("Radius:")); + init_val.setUnit(Base::Unit::Length); + } + ui_Datum.labelEdit->setValue(init_val); ui_Datum.labelEdit->selectNumber(); if (constrainEqual || geoIdRadiusMap.size() == 1) @@ -4989,7 +5117,14 @@ void CmdSketcherConstrainRadius::applyConstraint(std::vector &selSeq, // Create the radius constraint now openCommand(QT_TRANSLATE_NOOP("Command", "Add radius constraint")); - Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", + + bool ispole = isBsplinePole(geom); + + if(ispole) + Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Weight',%d,%f)) ", + GeoId, radius); + else + Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", GeoId, radius); const std::vector &ConStr = Obj->Constraints.getValues(); @@ -5022,10 +5157,19 @@ void CmdSketcherConstrainRadius::applyConstraint(std::vector &selSeq, QDialog dlg(Gui::getMainWindow()); Ui::InsertDatum ui_Datum; ui_Datum.setupUi(&dlg); - dlg.setWindowTitle(EditDatumDialog::tr("Change radius")); - ui_Datum.label->setText(EditDatumDialog::tr("Radius:")); Base::Quantity init_val; - init_val.setUnit(Base::Unit::Length); + + if(ispole) { + dlg.setWindowTitle(EditDatumDialog::tr("Change weight")); + ui_Datum.label->setText(EditDatumDialog::tr("Weight:")); + + } + else{ + dlg.setWindowTitle(EditDatumDialog::tr("Change radius")); + ui_Datum.label->setText(EditDatumDialog::tr("Radius:")); + init_val.setUnit(Base::Unit::Length); + } + init_val.setValue(radius); ui_Datum.labelEdit->setValue(init_val); @@ -5205,6 +5349,12 @@ void CmdSketcherConstrainDiameter::activated(int iMsg) const Part::GeomCircle *circle = static_cast(geom); double radius = circle->getRadius(); + if(isBsplinePole(geom)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + continue; + } + if(issegmentfixed) { externalGeoIdDiameterMap.push_back(std::make_pair(GeoId, 2*radius)); } @@ -5444,6 +5594,12 @@ void CmdSketcherConstrainDiameter::applyConstraint(std::vector &selSe return; } + if(isBsplinePole(geom)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + // Create the diameter constraint now openCommand(QT_TRANSLATE_NOOP("Command", "Add diameter constraint")); Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Diameter',%d,%f)) ", @@ -5768,6 +5924,13 @@ void CmdSketcherConstrainAngle::activated(int iMsg) bool bothexternal=areBothPointsOrSegmentsFixed(Obj, GeoId1, GeoId2); if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { + + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + double ActAngle = 0.0; openCommand(QT_TRANSLATE_NOOP("Command", "Add angle constraint")); @@ -5824,6 +5987,12 @@ void CmdSketcherConstrainAngle::activated(int iMsg) std::swap(PosId1,PosId2); } + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + if (isEdge(GeoId2,PosId2)) { // line to line angle const Part::Geometry *geom1 = Obj->getGeometry(GeoId1); @@ -6109,6 +6278,13 @@ void CmdSketcherConstrainAngle::applyConstraint(std::vector &selSeq, bool bothexternal=areBothPointsOrSegmentsFixed(Obj,GeoId1, GeoId2); if (isEdge(GeoId1, PosId1) && isEdge(GeoId2, PosId2) && isVertex(GeoId3, PosId3)) { + + if(isBsplinePole(Obj, GeoId1) || isBsplinePole(Obj, GeoId2)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + double ActAngle = 0.0; openCommand(QT_TRANSLATE_NOOP("Command", "Add angle constraint")); @@ -6241,7 +6417,7 @@ void CmdSketcherConstrainEqual::activated(int iMsg) std::vector ids; bool lineSel = false, arcSel = false, circSel = false, ellipsSel = false, arcEllipsSel=false, hasAlreadyExternal = false; - bool hyperbSel = false, parabSel=false; + bool hyperbSel = false, parabSel=false, weightSel=false; for (std::vector::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) { @@ -6279,20 +6455,30 @@ void CmdSketcherConstrainEqual::activated(int iMsg) return; } - if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) + if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { lineSel = true; - else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) + } + else if (geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { arcSel = true; - else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) - circSel = true; - else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) + } + else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { + if(isBsplinePole(geo)) + weightSel = true; + else + circSel = true; + } + else if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId()) { ellipsSel = true; - else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) + } + else if (geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) { arcEllipsSel = true; - else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) + } + else if (geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()) { hyperbSel = true; - else if (geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) + } + else if (geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId()) { parabSel = true; + } else { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select two or more edges of similar type")); @@ -6303,10 +6489,11 @@ void CmdSketcherConstrainEqual::activated(int iMsg) } // Check for heterogeneous groups in selection - if ( (lineSel && ((arcSel || circSel) || (ellipsSel || arcEllipsSel) || hyperbSel || parabSel) ) || - ((arcSel || circSel) && ((ellipsSel || arcEllipsSel) || hyperbSel || parabSel)) || - ((ellipsSel || arcEllipsSel) && (hyperbSel || parabSel)) || - (hyperbSel && parabSel) ) { + if ( (lineSel && ((arcSel || circSel) || (ellipsSel || arcEllipsSel) || hyperbSel || parabSel || weightSel) ) || + ((arcSel || circSel) && ((ellipsSel || arcEllipsSel) || hyperbSel || parabSel || weightSel)) || + ((ellipsSel || arcEllipsSel) && (hyperbSel || parabSel || weightSel)) || + ( hyperbSel && (parabSel || weightSel)) || + ( parabSel && weightSel)) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select two or more edges of similar type")); @@ -6348,6 +6535,23 @@ void CmdSketcherConstrainEqual::applyConstraint(std::vector &selSeq, return; } + const Part::Geometry *geo1 = Obj->getGeometry(GeoId1); + const Part::Geometry *geo2 = Obj->getGeometry(GeoId2); + + if ( (geo1->getTypeId() == Part::GeomLineSegment::getClassTypeId() && geo2->getTypeId() != Part::GeomLineSegment::getClassTypeId()) || + (geo1->getTypeId() == Part::GeomHyperbola::getClassTypeId() && geo2->getTypeId() != Part::GeomHyperbola::getClassTypeId()) || + (geo1->getTypeId() == Part::GeomParabola::getClassTypeId() && geo2->getTypeId() != Part::GeomParabola::getClassTypeId()) || + (isBsplinePole(geo1) && !isBsplinePole(geo1)) || + ( (geo1->getTypeId() == Part::GeomCircle::getClassTypeId() || geo1->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) && + (geo2->getTypeId() != Part::GeomCircle::getClassTypeId() || geo2->getTypeId() != Part::GeomArcOfCircle::getClassTypeId())) || + ( (geo1->getTypeId() == Part::GeomEllipse::getClassTypeId() || geo1->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()) && + (geo2->getTypeId() != Part::GeomEllipse::getClassTypeId() || geo2->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId())) ){ + + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select two or more edges of similar type")); + return; + } + // undo command open openCommand(QT_TRANSLATE_NOOP("Command", "Add equality constraint")); Gui::cmdAppObjectArgs(Obj, "addConstraint(Sketcher.Constraint('Equal',%d,%d)) ", @@ -6745,6 +6949,12 @@ void CmdSketcherConstrainSnellsLaw::activated(int iMsg) return; } + if(isBsplinePole(geo)) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge that is not a B-spline weight")); + return; + } + double n2divn1=0; //the essence. diff --git a/src/Mod/Sketcher/Gui/CommandConstraints.h b/src/Mod/Sketcher/Gui/CommandConstraints.h index 281872feac..f6a08d3632 100644 --- a/src/Mod/Sketcher/Gui/CommandConstraints.h +++ b/src/Mod/Sketcher/Gui/CommandConstraints.h @@ -51,6 +51,10 @@ bool isConstructionPoint(const Sketcher::SketchObject* Obj, int GeoId); bool IsPointAlreadyOnCurve(int GeoIdCurve, int GeoIdPoint, Sketcher::PointPos PosIdPoint, Sketcher::SketchObject* Obj); +bool isBsplinePole(const Part::Geometry * geo); + +bool isBsplinePole(const Sketcher::SketchObject* Obj, int GeoId); + /// Release any currently-active handler for the document. /// Returns true if a handler was released, and false if not bool ReleaseHandler(Gui::Document* doc); diff --git a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp index 35de045ee8..0a2939e7d8 100644 --- a/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp +++ b/src/Mod/Sketcher/Gui/CommandCreateGeo.cpp @@ -4134,33 +4134,12 @@ public: //Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Add Pole circle")); //Add pole - double guess = (EditCurve[1]-EditCurve[0]).Length()/6; - - auto normalize = [](double guess) { - double units=1.0; - - while (guess >= 10.0) { - guess /= 10.0; - units*=10.0; - } - - while (guess < 1.0) { - guess *= 10.0; - units/=10.0; - } - - return round(guess)*units; - - }; - - guess = normalize(guess); - Gui::cmdAppObjectArgs(sketchgui->getObject(), "addGeometry(Part.Circle(App.Vector(%f,%f,0),App.Vector(0,0,1),10),True)", EditCurve[EditCurve.size()-1].x,EditCurve[EditCurve.size()-1].y); if(EditCurve.size() == 2) { - Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('Radius',%d,%f)) ", - FirstPoleGeoId, guess ); + Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('Weight',%d,%f)) ", + FirstPoleGeoId, 1.0 ); // First pole defaults to 1.0 weight } Gui::cmdAppObjectArgs(sketchgui->getObject(), "addConstraint(Sketcher.Constraint('Equal',%d,%d)) ", diff --git a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp index 89a54d5e15..21ba1729bf 100644 --- a/src/Mod/Sketcher/Gui/EditDatumDialog.cpp +++ b/src/Mod/Sketcher/Gui/EditDatumDialog.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include "ViewProviderSketch.h" #include "ui_InsertDatum.h" @@ -81,13 +82,14 @@ void EditDatumDialog::exec(bool atCursor) return; } + Base::Quantity init_val; + QDialog dlg(Gui::getMainWindow()); if (ui_ins_datum == nullptr) { ui_ins_datum.reset(new Ui_InsertDatum); ui_ins_datum->setupUi(&dlg); } double datum = Constr->getValue(); - Base::Quantity init_val; if (Constr->Type == Sketcher::Angle) { datum = Base::toDegrees(datum); @@ -108,6 +110,11 @@ void EditDatumDialog::exec(bool atCursor) ui_ins_datum->label->setText(tr("Diameter:")); ui_ins_datum->labelEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/SketcherLength")); } + else if (Constr->Type == Sketcher::Weight) { + dlg.setWindowTitle(tr("Insert weight")); + ui_ins_datum->label->setText(tr("Weight:")); + ui_ins_datum->labelEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/SketcherWeight")); + } else if (Constr->Type == Sketcher::SnellsLaw) { dlg.setWindowTitle(tr("Refractive index ratio", "Constraint_SnellsLaw")); ui_ins_datum->label->setText(tr("Ratio n2/n1:", "Constraint_SnellsLaw")); @@ -155,7 +162,10 @@ void EditDatumDialog::exec(bool atCursor) void EditDatumDialog::accepted() { Base::Quantity newQuant = ui_ins_datum->labelEdit->value(); - if (newQuant.isQuantity() || (Constr->Type == Sketcher::SnellsLaw && newQuant.isDimensionless())) { + if( newQuant.isQuantity() || + (Constr->Type == Sketcher::SnellsLaw && newQuant.isDimensionless()) || + (Constr->Type == Sketcher::Weight && newQuant.isDimensionless())) { + // save the value for the history ui_ins_datum->labelEdit->pushToHistory(); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp index 1e5098366c..72378330df 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherConstrains.cpp @@ -138,6 +138,7 @@ public: case Sketcher::DistanceX: case Sketcher::DistanceY: case Sketcher::Radius: + case Sketcher::Weight: case Sketcher::Diameter: case Sketcher::Angle: name = QString::fromLatin1("%1 (%2)").arg(name).arg(constraint->getPresentationValue().getUserString()); @@ -257,6 +258,7 @@ public: case Sketcher::DistanceY: return selicon(constraint,vdist,vdist_driven); case Sketcher::Radius: + case Sketcher::Weight: return selicon(constraint,radi,radi_driven); case Sketcher::Diameter: return selicon(constraint,dia,dia_driven); @@ -326,6 +328,7 @@ public: case Sketcher::DistanceY: case Sketcher::Radius: case Sketcher::Diameter: + case Sketcher::Weight: case Sketcher::Angle: case Sketcher::SnellsLaw: return ( constraint->First >= 0 || constraint->Second >= 0 || constraint->Third >= 0 ); @@ -945,6 +948,7 @@ void TaskSketcherConstrains::slotConstraintsChanged(void) case Sketcher::DistanceX: case Sketcher::DistanceY: case Sketcher::Radius: + case Sketcher::Weight: case Sketcher::Diameter: case Sketcher::Angle: case Sketcher::SnellsLaw: diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 178cfb0452..89a910b53c 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -842,9 +842,29 @@ bool ViewProviderSketch::mouseButtonPressed(int Button, bool pressed, const SbVe geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId()|| geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { getDocument()->openCommand(QT_TRANSLATE_NOOP("Command", "Drag Curve")); + + auto geo = getSketchObject()->getGeometry(edit->DragCurve); + auto gf = GeometryFacade::getFacade(geo); + + Base::Vector3d vec(x-xInit,y-yInit,0); + + // BSpline weights have a radius corresponding to the weight value + // However, in order for them to have a visual size irrespective of the + // zoom, the scenograph has a size getScaleFactor() times the weight + // + // This code normalizes the information sent to the solver. + if(gf->getInternalType() == InternalType::BSplineControlPoint) { + auto circle = static_cast(geo); + Base::Vector3d center = circle->getCenter(); + + Base::Vector3d dir = vec - center; + + vec = center - dir / getScaleFactor(); + } + try { Gui::cmdAppObjectArgs(getObject(), "movePoint(%i,%i,App.Vector(%f,%f,0),%i)" - ,edit->DragCurve, Sketcher::none, x-xInit, y-yInit, relative ? 1 : 0); + ,edit->DragCurve, Sketcher::none, vec.x, vec.y, relative ? 1 : 0); getDocument()->commitCommand(); tryAutoRecomputeIfNotSolve(getSketchObject()); @@ -1133,7 +1153,7 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor getSketchObject()->getSolvedSketch().initMove(edit->DragCurve, Sketcher::none, false); const Part::Geometry *geo = getSketchObject()->getGeometry(edit->DragCurve); if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId() || - geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId() ) { + geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) { relative = true; //xInit = x; //yInit = y; @@ -1185,7 +1205,25 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor return true; case STATUS_SKETCH_DragCurve: if (edit->DragCurve != -1) { + auto geo = getSketchObject()->getGeometry(edit->DragCurve); + auto gf = GeometryFacade::getFacade(geo); + Base::Vector3d vec(x-xInit,y-yInit,0); + + // BSpline weights have a radius corresponding to the weight value + // However, in order for them to have a visual size irrespective of the + // zoom, the scenograph has a size getScaleFactor() times the weight + // + // This code normalizes the information sent to the solver. + if(gf->getInternalType() == InternalType::BSplineControlPoint) { + auto circle = static_cast(geo); + Base::Vector3d center = circle->getCenter(); + + Base::Vector3d dir = vec - center; + + vec = center - dir / getScaleFactor(); + } + if (getSketchObject()->getSolvedSketch().movePoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) { setPositionText(Base::Vector2d(x,y)); draw(true,false); @@ -1261,7 +1299,7 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo #endif if (Constr->Type == Distance || Constr->Type == DistanceX || Constr->Type == DistanceY || - Constr->Type == Radius || Constr->Type == Diameter) { + Constr->Type == Radius || Constr->Type == Diameter || Constr-> Type == Weight) { Base::Vector3d p1(0.,0.,0.), p2(0.,0.,0.); if (Constr->SecondPos != Sketcher::none) { // point to point distance @@ -1331,14 +1369,14 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo Base::Vector3d vec = Base::Vector3d(toPos.x, toPos.y, 0) - p2; Base::Vector3d dir; - if (Constr->Type == Distance || Constr->Type == Radius || Constr->Type == Diameter) + if (Constr->Type == Distance || Constr->Type == Radius || Constr->Type == Diameter || Constr->Type == Weight) dir = (p2-p1).Normalize(); else if (Constr->Type == DistanceX) dir = Base::Vector3d( (p2.x - p1.x >= FLT_EPSILON) ? 1 : -1, 0, 0); else if (Constr->Type == DistanceY) dir = Base::Vector3d(0, (p2.y - p1.y >= FLT_EPSILON) ? 1 : -1, 0); - if (Constr->Type == Radius || Constr->Type == Diameter) { + if (Constr->Type == Radius || Constr->Type == Diameter || Constr->Type == Weight) { Constr->LabelDistance = vec.x * dir.x + vec.y * dir.y; Constr->LabelPosition = atan2(dir.y, dir.x); } else { @@ -2804,6 +2842,7 @@ void ViewProviderSketch::updateColor(void) bool hasDatumLabel = (type == Sketcher::Angle || type == Sketcher::Radius || type == Sketcher::Diameter || + type == Sketcher::Weight || type == Sketcher::Symmetric || type == Sketcher::Distance || type == Sketcher::DistanceX || @@ -3621,18 +3660,69 @@ void ViewProviderSketch::draw(bool temp /*=false*/, bool rebuildinformationlayer else if ((*it)->getTypeId() == Part::GeomCircle::getClassTypeId()) { // add a circle const Part::GeomCircle *circle = static_cast(*it); Handle(Geom_Circle) curve = Handle(Geom_Circle)::DownCast(circle->handle()); + auto gf = GeometryFacade::getFacade(circle); int countSegments = stdcountsegments; Base::Vector3d center = circle->getCenter(); - double segment = (2 * M_PI) / countSegments; - for (int i=0; i < countSegments; i++) { - gp_Pnt pnt = curve->Value(i*segment); + + // BSpline weights have a radius corresponding to the weight value + // However, in order for them to have a visual size irrespective of the + // zoom, the scenograph has a size getScaleFactor() times the weight + // + // This code draws the scaled up version of the geometry for the scenograph + if(gf->getInternalType() == InternalType::BSplineControlPoint) { + for( auto c : getSketchObject()->Constraints.getValues()) { + if( c->Type == InternalAlignment && c->AlignmentType == BSplineControlPoint && c->First == GeoId) { + auto bspline = dynamic_cast((*geomlist)[c->Second]); + + if(bspline){ + auto weights = bspline->getWeights(); + + double weight = 1.0; + if(c->InternalAlignmentIndex < int(weights.size())) + weight = weights[c->InternalAlignmentIndex]; + + // tentative scaling factor: + // proportional to the length of the bspline + // inversely proportional to the number of poles + //double scalefactor = bspline->length(bspline->getFirstParameter(), bspline->getLastParameter())/10.0/weights.size(); + double scalefactor = getScaleFactor(); + double vradius = weight*scalefactor; + + // virtual circle or radius vradius + auto mcurve = [¢er, vradius](double param, double &x, double &y) { + x = center.x + vradius*cos(param); + y = center.y + vradius*sin(param); + }; + + double x; + double y; + for (int i=0; i < countSegments; i++) { + double param = 2*M_PI*i/countSegments; + mcurve(param,x,y); + Coords.emplace_back(x, y, 0); + } + + mcurve(0,x,y); + Coords.emplace_back(x, y, 0); + } + break; + } + } + } + else { + + double segment = (2 * M_PI) / countSegments; + + for (int i=0; i < countSegments; i++) { + gp_Pnt pnt = curve->Value(i*segment); + Coords.emplace_back(pnt.X(), pnt.Y(), pnt.Z()); + } + + gp_Pnt pnt = curve->Value(0); Coords.emplace_back(pnt.X(), pnt.Y(), pnt.Z()); } - gp_Pnt pnt = curve->Value(0); - Coords.emplace_back(pnt.X(), pnt.Y(), pnt.Z()); - Index.push_back(countSegments+1); edit->CurvIdToGeoId.push_back(GeoId); Points.push_back(center); @@ -5344,11 +5434,13 @@ Restart: asciiText->pnts.finishEditing(); } break; + case Weight: case Radius: { assert(Constr->First >= -extGeoCount && Constr->First < intGeoCount); Base::Vector3d pnt1(0.,0.,0.), pnt2(0.,0.,0.); + if (Constr->First != Constraint::GeoUndef) { const Part::Geometry *geo = GeoById(*geomlist, Constr->First); @@ -5366,7 +5458,15 @@ Restart: } else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { const Part::GeomCircle *circle = static_cast(geo); - double radius = circle->getRadius(); + auto gf = GeometryFacade::getFacade(geo); + + double radius; + + if(Constr->Type == Weight) + radius = circle->getRadius()*getScaleFactor(); + else + radius = circle->getRadius(); + double angle = (double) Constr->LabelPosition; if (angle == 10) { angle = 0; @@ -5385,7 +5485,10 @@ Restart: SoDatumLabel *asciiText = static_cast(sep->getChild(CONSTRAINT_SEPARATOR_INDEX_MATERIAL_OR_DATUMLABEL)); // Get display string with units hidden if so requested - asciiText->string = SbString( getPresentationString(Constr).toUtf8().constData() ); + if(Constr->Type == Weight) + asciiText->string = SbString( QString::number(Constr->getValue()).toStdString().c_str()); + else + asciiText->string = SbString( getPresentationString(Constr).toUtf8().constData() ); asciiText->datumtype = SoDatumLabel::RADIUS; asciiText->param1 = Constr->LabelDistance; @@ -5475,6 +5578,7 @@ void ViewProviderSketch::rebuildConstraintsVisual(void) case DistanceY: case Radius: case Diameter: + case Weight: case Angle: { SoDatumLabel *text = new SoDatumLabel();