Sketcher: Add circle to circle distance constraint
This commit is contained in:
committed by
abdullahtahiriyo
parent
0e64e76514
commit
21c2eb6014
@@ -224,14 +224,6 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
if (PyNumber_Check(index_or_value)) { // can be float or int
|
||||
SecondIndex = any_index;
|
||||
Value = PyFloat_AsDouble(index_or_value);
|
||||
//if (strcmp("Distance",ConstraintType) == 0) {
|
||||
// this->getConstraintPtr()->Type = Distance;
|
||||
// this->getConstraintPtr()->First = FirstIndex;
|
||||
// this->getConstraintPtr()->Second = SecondIndex;
|
||||
// this->getConstraintPtr()->Value = Value;
|
||||
// return 0;
|
||||
//}
|
||||
//else
|
||||
if (strcmp("Angle",ConstraintType) == 0) {
|
||||
if (PyObject_TypeCheck(index_or_value, &(Base::QuantityPy::Type))) {
|
||||
Base::Quantity q = *(static_cast<Base::QuantityPy*>(index_or_value)->getQuantityPtr());
|
||||
@@ -244,6 +236,13 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
||||
this->getConstraintPtr()->setValue(Value);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp("Distance",ConstraintType) == 0) {
|
||||
this->getConstraintPtr()->Type = Distance;
|
||||
this->getConstraintPtr()->First = FirstIndex;
|
||||
this->getConstraintPtr()->Second = SecondIndex;
|
||||
this->getConstraintPtr()->setValue(Value);
|
||||
return 0;
|
||||
}
|
||||
else if (strcmp("DistanceX",ConstraintType) == 0) {
|
||||
FirstPos = SecondIndex;
|
||||
SecondIndex = -1;
|
||||
@@ -481,7 +480,7 @@ std::string ConstraintPy::representation() const
|
||||
case Coincident : result << "'Coincident'>";break;
|
||||
case Horizontal : result << "'Horizontal' (" << getConstraintPtr()->First << ")>";break;
|
||||
case Vertical : result << "'Vertical' (" << getConstraintPtr()->First << ")>";break;
|
||||
case Block : result << "'Block' (" << getConstraintPtr()->First << ")>";break;
|
||||
case Block : result << "'Block' (" << getConstraintPtr()->First << ")>";break;
|
||||
case Radius : result << "'Radius'>";break;
|
||||
case Diameter : result << "'Diameter'>";break;
|
||||
case Weight : result << "'Weight'>";break;
|
||||
|
||||
@@ -296,6 +296,10 @@ std::string PythonConverter::process(const Sketcher::Constraint * constraint)
|
||||
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %f)") %
|
||||
constr->First % constr->getValue());
|
||||
}
|
||||
else if(constr->FirstPos == Sketcher::PointPos::none){
|
||||
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %f)") %
|
||||
constr->First % constr->Second % constr->getValue());
|
||||
}
|
||||
else if(constr->SecondPos == Sketcher::PointPos::none){
|
||||
return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %f)") %
|
||||
constr->First % static_cast<int>(constr->FirstPos) % constr->Second % constr->getValue());
|
||||
|
||||
@@ -1797,6 +1797,20 @@ int Sketch::addConstraint(const Constraint *constraint)
|
||||
constraint->Second,constraint->SecondPos,
|
||||
c.value,c.driving);
|
||||
}
|
||||
else if (constraint->FirstPos == PointPos::none &&
|
||||
constraint->SecondPos == PointPos::none &&
|
||||
constraint->Second != GeoEnum::GeoUndef &&
|
||||
constraint->Third == GeoEnum::GeoUndef) { // circle to circle, circle to arc, etc.
|
||||
|
||||
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 = addDistanceConstraint(constraint->First, constraint->Second,c.value,c.driving);
|
||||
}
|
||||
else if (constraint->Second != GeoEnum::GeoUndef) {
|
||||
if (constraint->FirstPos != PointPos::none) { // point to line distance
|
||||
c.value = new double(constraint->getValue());
|
||||
@@ -1806,8 +1820,7 @@ int Sketch::addConstraint(const Constraint *constraint)
|
||||
Parameters.push_back(c.value);
|
||||
DrivenParameters.push_back(c.value);
|
||||
}
|
||||
rtn = addDistanceConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,c.value,c.driving);
|
||||
rtn = addDistanceConstraint(constraint->First,constraint->FirstPos,constraint->Second,c.value,c.driving);
|
||||
}
|
||||
}
|
||||
else {// line length
|
||||
@@ -2740,6 +2753,19 @@ int Sketch::addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPo
|
||||
return -1;
|
||||
}
|
||||
|
||||
// circle-circle offset distance constraint
|
||||
int Sketch::addDistanceConstraint(int geoId1, int geoId2, double * value, bool driving)
|
||||
{
|
||||
if ((Geoms[geoId1].type == Circle) && (Geoms[geoId2].type == Circle)) {
|
||||
GCS::Circle &c1 = Circles[Geoms[geoId1].index];
|
||||
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintC2CDistance(c1, c2, value, tag, driving);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Sketch::addRadiusConstraint(int geoId, double * value, bool driving)
|
||||
{
|
||||
geoId = checkGeoId(geoId);
|
||||
|
||||
@@ -276,6 +276,15 @@ public:
|
||||
* Parameters array, as the case may be.
|
||||
*/
|
||||
int addDistanceConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, double * value, bool driving = true);
|
||||
/**
|
||||
* add a length or distance constraint
|
||||
*
|
||||
* double * value is a pointer to double allocated in the heap, containing the
|
||||
* constraint value and already inserted into either the FixParameters or
|
||||
* Parameters array, as the case may be.
|
||||
*/
|
||||
int addDistanceConstraint(int geoId1, int geoId2, double * value, bool driving = true);
|
||||
|
||||
/// add a parallel constraint between two lines
|
||||
int addParallelConstraint(int geoId1, int geoId2);
|
||||
/// add a perpendicular constraint between two lines
|
||||
|
||||
@@ -2585,5 +2585,109 @@ double ConstraintEqualLineLength::grad(double *param)
|
||||
return deriv*scale;
|
||||
}
|
||||
|
||||
// ConstraintC2CDistance
|
||||
ConstraintC2CDistance::ConstraintC2CDistance(Circle &c1, Circle &c2, double *d)
|
||||
{
|
||||
this->d = d;
|
||||
pvec.push_back(d);
|
||||
|
||||
this->c1 = c1;
|
||||
this->c1.PushOwnParams(pvec);
|
||||
|
||||
this->c2 = c2;
|
||||
this->c2.PushOwnParams(pvec);
|
||||
|
||||
origpvec = pvec;
|
||||
pvecChangedFlag = true;
|
||||
rescale();
|
||||
}
|
||||
|
||||
void ConstraintC2CDistance::ReconstructGeomPointers()
|
||||
{
|
||||
int i=0;
|
||||
i++; // skip the first parameter as there is the inline function distance for it
|
||||
c1.ReconstructOnNewPvec(pvec, i);
|
||||
c2.ReconstructOnNewPvec(pvec, i);
|
||||
pvecChangedFlag = false;
|
||||
}
|
||||
|
||||
ConstraintType ConstraintC2CDistance::getTypeId()
|
||||
{
|
||||
return C2CDistance;
|
||||
}
|
||||
|
||||
void ConstraintC2CDistance::rescale(double coef)
|
||||
{
|
||||
scale = coef * 1;
|
||||
}
|
||||
|
||||
void ConstraintC2CDistance::errorgrad(double *err, double *grad, double *param)
|
||||
{
|
||||
if (pvecChangedFlag) ReconstructGeomPointers();
|
||||
|
||||
DeriVector2 ct1 (c1.center, param);
|
||||
DeriVector2 ct2 (c2.center, param);
|
||||
|
||||
DeriVector2 vector_ct12 = ct1.subtr(ct2);
|
||||
|
||||
double length_ct12, dlength_ct12;
|
||||
length_ct12 = vector_ct12.length(dlength_ct12);
|
||||
|
||||
// outer case (defined as the centers of the circles are outside the center of the other circles)
|
||||
// it may well be that the circles intersect.
|
||||
if( length_ct12 >= *c1.rad &&
|
||||
length_ct12 >= *c2.rad ) {
|
||||
if (err) {
|
||||
*err = length_ct12 - (*c2.rad + *c1.rad + *distance());
|
||||
}
|
||||
else if (grad) {
|
||||
double drad = (param == c2.rad || param == c1.rad || param == distance())?-1.0:0.0;
|
||||
*grad = dlength_ct12 + drad;
|
||||
}
|
||||
}
|
||||
else {
|
||||
double * bigradius = (*c1.rad >= *c2.rad)?c1.rad:c2.rad;
|
||||
double * smallradius = (*c1.rad >= *c2.rad)?c2.rad:c1.rad;
|
||||
|
||||
double smallspan = *smallradius + length_ct12 + *distance();
|
||||
|
||||
if (err) {
|
||||
*err = *bigradius - smallspan;
|
||||
}
|
||||
else if (grad) {
|
||||
double drad = 0.0;
|
||||
|
||||
if(param == bigradius) {
|
||||
drad = 1.0;
|
||||
}
|
||||
else if(param == smallradius) {
|
||||
drad = -1.0;
|
||||
}
|
||||
else if(param == distance()) {
|
||||
drad = (*distance()<0.)?1.0:-1.0;
|
||||
}
|
||||
|
||||
*grad = -dlength_ct12 + drad;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double ConstraintC2CDistance::error()
|
||||
{
|
||||
double err;
|
||||
errorgrad(&err,nullptr,nullptr);
|
||||
return scale * err;
|
||||
}
|
||||
|
||||
double ConstraintC2CDistance::grad(double *param)
|
||||
{
|
||||
if ( findParamInPvec(param) == -1 )
|
||||
return 0.0;
|
||||
|
||||
double deriv;
|
||||
errorgrad(nullptr, &deriv, param);
|
||||
|
||||
return deriv*scale;
|
||||
}
|
||||
|
||||
} //namespace GCS
|
||||
|
||||
@@ -72,7 +72,8 @@ namespace GCS
|
||||
CenterOfGravity = 26,
|
||||
WeightedLinearCombination = 27,
|
||||
SlopeAtBSplineKnot = 28,
|
||||
PointOnBSpline = 29
|
||||
PointOnBSpline = 29,
|
||||
C2CDistance = 30
|
||||
};
|
||||
|
||||
enum InternalAlignmentType {
|
||||
@@ -745,6 +746,22 @@ namespace GCS
|
||||
double grad(double *) override;
|
||||
};
|
||||
|
||||
class ConstraintC2CDistance : public Constraint
|
||||
{
|
||||
private:
|
||||
Circle c1;
|
||||
Circle c2;
|
||||
double *d;
|
||||
inline double* distance() { return pvec[0]; }
|
||||
void ReconstructGeomPointers(); //writes pointers in pvec to the parameters of c1, c2
|
||||
void errorgrad(double* err, double* grad, double *param); //error and gradient combined. Values are returned through pointers.
|
||||
public:
|
||||
ConstraintC2CDistance(Circle &c1, Circle &c2, double *d);
|
||||
ConstraintType getTypeId() override;
|
||||
void rescale(double coef=1.) override;
|
||||
double error() override;
|
||||
double grad(double *) override;
|
||||
};
|
||||
|
||||
} //namespace GCS
|
||||
|
||||
|
||||
@@ -817,6 +817,14 @@ int System::addConstraintTangentAtBSplineKnot(BSpline &b, Line &l, unsigned int
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintC2CDistance(Circle &c1, Circle &c2, double *dist, int tagId, bool driving)
|
||||
{
|
||||
Constraint *constr = new ConstraintC2CDistance(c1, c2, dist);
|
||||
constr->setTag(tagId);
|
||||
constr->setDriving(driving);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
// derived constraints
|
||||
|
||||
int System::addConstraintP2PCoincident(Point &p1, Point &p2, int tagId, bool driving)
|
||||
|
||||
@@ -315,6 +315,8 @@ namespace GCS
|
||||
bool flipn1, bool flipn2,
|
||||
int tagId, bool driving = true);
|
||||
|
||||
int addConstraintC2CDistance(Circle &c1, Circle &c2, double *dist, int tagId, bool driving = true);
|
||||
|
||||
// internal alignment constraints
|
||||
int addConstraintInternalAlignmentPoint2Ellipse(Ellipse &e, Point &p1, InternalAlignmentType alignmentType, int tagId=0, bool driving = true);
|
||||
int addConstraintInternalAlignmentEllipseMajorDiameter(Ellipse &e, Point &p1, Point &p2, int tagId=0, bool driving = true);
|
||||
|
||||
@@ -2150,7 +2150,7 @@ CmdSketcherConstrainDistance::CmdSketcherConstrainDistance()
|
||||
sAppModule = "Sketcher";
|
||||
sGroup = "Sketcher";
|
||||
sMenuText = QT_TR_NOOP("Constrain distance");
|
||||
sToolTipText = QT_TR_NOOP("Fix a length of a line or the distance between a line and a vertex");
|
||||
sToolTipText = QT_TR_NOOP("Fix a length of a line or the distance between a line and a vertex or between two circles");
|
||||
sWhatsThis = "Sketcher_ConstrainDistance";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "Constraint_Length";
|
||||
@@ -2160,7 +2160,8 @@ CmdSketcherConstrainDistance::CmdSketcherConstrainDistance()
|
||||
allowedSelSequences = {{SelVertex, SelVertexOrRoot}, {SelRoot, SelVertex},
|
||||
{SelEdge}, {SelExternalEdge},
|
||||
{SelVertex, SelEdgeOrAxis}, {SelRoot, SelEdge},
|
||||
{SelVertex, SelExternalEdge}, {SelRoot, SelExternalEdge}};
|
||||
{SelVertex, SelExternalEdge}, {SelRoot, SelExternalEdge},
|
||||
{SelEdge, SelEdge}};
|
||||
}
|
||||
|
||||
void CmdSketcherConstrainDistance::activated(int iMsg)
|
||||
@@ -2289,6 +2290,55 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isEdge(GeoId1,PosId1) && isEdge(GeoId2,PosId2)) { // circle to circle distance
|
||||
const Part::Geometry *geom1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geom2 = Obj->getGeometry(GeoId2);
|
||||
if (geom1->getTypeId() == Part::GeomCircle::getClassTypeId()
|
||||
&& geom2->getTypeId() == Part::GeomCircle::getClassTypeId() ) {
|
||||
auto circleSeg1 = static_cast<const Part::GeomCircle*>(geom1);
|
||||
double radius1 = circleSeg1->getRadius();
|
||||
Base::Vector3d center1 = circleSeg1->getCenter();
|
||||
|
||||
auto circleSeg2 = static_cast<const Part::GeomCircle*>(geom2);
|
||||
double radius2 = circleSeg2->getRadius();
|
||||
Base::Vector3d center2 = circleSeg2->getCenter();
|
||||
|
||||
double ActDist = 0.;
|
||||
|
||||
Base::Vector3d intercenter = center1 - center2;
|
||||
double intercenterdistance = intercenter.Length();
|
||||
|
||||
if( intercenterdistance >= radius1 &&
|
||||
intercenterdistance >= radius2 ) {
|
||||
|
||||
ActDist = intercenterdistance - radius1 - radius2;
|
||||
}
|
||||
else {
|
||||
double bigradius = std::max(radius1,radius2);
|
||||
double smallradius = std::min(radius1,radius2);
|
||||
|
||||
ActDist = bigradius - smallradius - intercenterdistance;
|
||||
}
|
||||
|
||||
openCommand(QT_TRANSLATE_NOOP("Command", "Add circle to circle distance constraint"));
|
||||
Gui::cmdAppObjectArgs(selection[0].getObject(),
|
||||
"addConstraint(Sketcher.Constraint('Distance',%d,%d,%f)) ",
|
||||
GeoId1,GeoId2,ActDist);
|
||||
|
||||
if (arebothpointsorsegmentsfixed || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving
|
||||
const std::vector<Sketcher::Constraint *> &ConStr = Obj->Constraints.getValues();
|
||||
|
||||
Gui::cmdAppObjectArgs(selection[0].getObject(),
|
||||
"setDriving(%i,%s)",
|
||||
ConStr.size()-1,"False");
|
||||
finishDatumConstraint (this, Obj, false);
|
||||
}
|
||||
else
|
||||
finishDatumConstraint (this, Obj, true);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (isEdge(GeoId1,PosId1)) { // line length
|
||||
if (GeoId1 < 0 && GeoId1 >= Sketcher::GeoEnum::VAxis) {
|
||||
Gui::TranslatedNotification(Obj,
|
||||
@@ -2327,7 +2377,7 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
|
||||
|
||||
Gui::TranslatedNotification(Obj,
|
||||
QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly one line or one point and one line or two points from the sketch."));
|
||||
QObject::tr("Select exactly one line or one point and one line or two points or two circles from the sketch."));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2416,6 +2466,9 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector<SelIdPair> &selSe
|
||||
else
|
||||
finishDatumConstraint (this, Obj, true);
|
||||
}
|
||||
else if (geom->getTypeId() == Part::GeomCircle::getClassTypeId()) {
|
||||
// allow this selection but do nothing as it needs 2 circles
|
||||
}
|
||||
else {
|
||||
Gui::TranslatedNotification(Obj,
|
||||
QObject::tr("Wrong selection"),
|
||||
@@ -2460,6 +2513,61 @@ void CmdSketcherConstrainDistance::applyConstraint(std::vector<SelIdPair> &selSe
|
||||
|
||||
return;
|
||||
}
|
||||
case 8: // {SelEdge, SelEdge}
|
||||
{
|
||||
GeoId1 = selSeq.at(0).GeoId; GeoId2 = selSeq.at(1).GeoId;
|
||||
const Part::Geometry *geom1 = Obj->getGeometry(GeoId1);
|
||||
const Part::Geometry *geom2 = Obj->getGeometry(GeoId2);
|
||||
if (geom1->getTypeId() == Part::GeomCircle::getClassTypeId()
|
||||
&& geom2->getTypeId() == Part::GeomCircle::getClassTypeId() ) { // circle to circle distance
|
||||
auto circleSeg1 = static_cast<const Part::GeomCircle*>(geom1);
|
||||
double radius1 = circleSeg1->getRadius();
|
||||
Base::Vector3d center1 = circleSeg1->getCenter();
|
||||
|
||||
auto circleSeg2 = static_cast<const Part::GeomCircle*>(geom2);
|
||||
double radius2 = circleSeg2->getRadius();
|
||||
Base::Vector3d center2 = circleSeg2->getCenter();
|
||||
|
||||
double ActDist = 0.;
|
||||
|
||||
Base::Vector3d intercenter = center1 - center2;
|
||||
double intercenterdistance = intercenter.Length();
|
||||
|
||||
if( intercenterdistance >= radius1 &&
|
||||
intercenterdistance >= radius2 ) {
|
||||
|
||||
ActDist = intercenterdistance - radius1 - radius2;
|
||||
}
|
||||
else {
|
||||
double bigradius = std::max(radius1,radius2);
|
||||
double smallradius = std::min(radius1,radius2);
|
||||
|
||||
ActDist = bigradius - smallradius - intercenterdistance;
|
||||
}
|
||||
|
||||
openCommand(QT_TRANSLATE_NOOP("Command", "Add circle to circle distance constraint"));
|
||||
Gui::cmdAppObjectArgs(Obj,
|
||||
"addConstraint(Sketcher.Constraint('Distance',%d,%d,%f)) ",
|
||||
GeoId1,GeoId2,ActDist);
|
||||
|
||||
if (arebothpointsorsegmentsfixed || constraintCreationMode==Reference) { // it is a constraint on a external line, make it non-driving
|
||||
const std::vector<Sketcher::Constraint *> &ConStr = Obj->Constraints.getValues();
|
||||
|
||||
Gui::cmdAppObjectArgs(Obj, "setDriving(%i,%s)",
|
||||
ConStr.size()-1,"False");
|
||||
finishDatumConstraint (this, Obj, false);
|
||||
}
|
||||
else
|
||||
finishDatumConstraint (this, Obj, true);
|
||||
|
||||
return;
|
||||
} else {
|
||||
Gui::TranslatedNotification(Obj,
|
||||
QObject::tr("Wrong selection"),
|
||||
QObject::tr("Select exactly one line or one point and one line or two points or two circles from the sketch."));
|
||||
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "SoZoomTranslation.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "ViewProviderSketchCoinAttorney.h"
|
||||
#include "Utils.h"
|
||||
|
||||
|
||||
using namespace SketcherGui;
|
||||
@@ -654,24 +655,33 @@ Restart:
|
||||
if (Constr->SecondPos != Sketcher::PointPos::none) { // point to point distance
|
||||
pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos);
|
||||
pnt2 = geolistfacade.getPoint(Constr->Second, Constr->SecondPos);
|
||||
} else if (Constr->Second != GeoEnum::GeoUndef) { // point to line distance
|
||||
} else if (Constr->Second != GeoEnum::GeoUndef) {
|
||||
pnt1 = geolistfacade.getPoint(Constr->First, Constr->FirstPos);
|
||||
|
||||
const Part::Geometry *geo = geolistfacade.getGeometryFromGeoId(Constr->Second);
|
||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // point to line distance
|
||||
const Part::GeomLineSegment *lineSeg = static_cast<const Part::GeomLineSegment *>(geo);
|
||||
Base::Vector3d l2p1 = lineSeg->getStartPoint();
|
||||
Base::Vector3d l2p2 = lineSeg->getEndPoint();
|
||||
// calculate the projection of p1 onto line2
|
||||
pnt2.ProjectToLine(pnt1-l2p1, l2p2-l2p1);
|
||||
pnt2 += pnt1;
|
||||
|
||||
} else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { // circle to circle distance
|
||||
const Part::Geometry *geo1 = geolistfacade.getGeometryFromGeoId(Constr->First);
|
||||
if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
|
||||
const Part::GeomCircle *circleSeg1 = static_cast<const Part::GeomCircle*>(geo1);
|
||||
auto circleSeg2 = static_cast<const Part::GeomCircle*>(geo);
|
||||
GetCirclesMinimalDistance(circleSeg1, circleSeg2, pnt1, pnt2);
|
||||
}
|
||||
|
||||
} else
|
||||
break;
|
||||
} else if (Constr->FirstPos != Sketcher::PointPos::none) {
|
||||
pnt2 = geolistfacade.getPoint(Constr->First, Constr->FirstPos);
|
||||
} else if (Constr->First != GeoEnum::GeoUndef) {
|
||||
const Part::Geometry *geo = geolistfacade.getGeometryFromGeoId(Constr->First);
|
||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // segment distance
|
||||
const Part::GeomLineSegment *lineSeg = static_cast<const Part::GeomLineSegment *>(geo);
|
||||
pnt1 = lineSeg->getStartPoint();
|
||||
pnt2 = lineSeg->getEndPoint();
|
||||
|
||||
@@ -327,6 +327,39 @@ double SketcherGui::GetPointAngle(const Base::Vector2d& p1, const Base::Vector2d
|
||||
return dY >= 0 ? atan2(dY, dX) : atan2(dY, dX) + 2 * M_PI;
|
||||
}
|
||||
|
||||
// Set the two points on circles at minimal distance
|
||||
// in concentric case set points on relative X axis
|
||||
void SketcherGui::GetCirclesMinimalDistance(const Part::GeomCircle *circle1, const Part::GeomCircle *circle2, Base::Vector3d &point1, Base::Vector3d &point2)
|
||||
{
|
||||
double radius1 = circle1->getRadius();
|
||||
double radius2 = circle2->getRadius();
|
||||
|
||||
point1 = circle1->getCenter();
|
||||
point2 = circle2->getCenter();
|
||||
|
||||
Base::Vector3d v = point2 - point1;
|
||||
double length = v.Length();
|
||||
|
||||
if (length == 0) { //concentric case
|
||||
point1.x += radius1;
|
||||
point2.x += radius2;
|
||||
} else {
|
||||
v = v.Normalize();
|
||||
if (length <= std::max(radius1, radius2)){ //inner case
|
||||
if (radius1 > radius2){
|
||||
point1 += v * radius1;
|
||||
point2 += v * radius2;
|
||||
} else {
|
||||
point1 += -v * radius1;
|
||||
point2 += -v * radius2;
|
||||
}
|
||||
} else { //outer case
|
||||
point1 += v * radius1;
|
||||
point2 += -v * radius2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SketcherGui::ActivateHandler(Gui::Document* doc, DrawSketchHandler* handler)
|
||||
{
|
||||
std::unique_ptr<DrawSketchHandler> ptr(handler);
|
||||
|
||||
@@ -119,6 +119,9 @@ inline bool isEdge(int GeoId, Sketcher::PointPos PosId)
|
||||
// Return counter-clockwise angle from horizontal out of p1 to p2 in radians.
|
||||
double GetPointAngle (const Base::Vector2d &p1, const Base::Vector2d &p2);
|
||||
|
||||
// Set the two points on circles at minimal distance
|
||||
void GetCirclesMinimalDistance(const Part::GeomCircle *circle1, const Part::GeomCircle *circle2, Base::Vector3d &point1, Base::Vector3d &point2);
|
||||
|
||||
void ActivateHandler(Gui::Document *doc, DrawSketchHandler *handler);
|
||||
|
||||
/// Returns if a sketch is in edit mode
|
||||
|
||||
@@ -1416,16 +1416,23 @@ void ViewProviderSketch::moveConstraint(int constNum, const Base::Vector2d &toPo
|
||||
if (Constr->SecondPos != Sketcher::PointPos::none) { // point to point distance
|
||||
p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
|
||||
p2 = getSolvedSketch().getPoint(Constr->Second, Constr->SecondPos);
|
||||
} else if (Constr->Second != GeoEnum::GeoUndef) { // point to line distance
|
||||
} else if (Constr->Second != GeoEnum::GeoUndef) {
|
||||
p1 = getSolvedSketch().getPoint(Constr->First, Constr->FirstPos);
|
||||
const Part::Geometry *geo = GeoList::getGeometryFromGeoId (geomlist, Constr->Second);
|
||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) { // point to line distance
|
||||
const Part::GeomLineSegment *lineSeg = static_cast<const Part::GeomLineSegment *>(geo);
|
||||
Base::Vector3d l2p1 = lineSeg->getStartPoint();
|
||||
Base::Vector3d l2p2 = lineSeg->getEndPoint();
|
||||
// calculate the projection of p1 onto line2
|
||||
p2.ProjectToLine(p1-l2p1, l2p2-l2p1);
|
||||
p2 += p1;
|
||||
} else if (geo->getTypeId() == Part::GeomCircle::getClassTypeId()) { // circle to circle distance
|
||||
const Part::Geometry *geo1 = GeoList::getGeometryFromGeoId (geomlist, Constr->First);
|
||||
if (geo1->getTypeId() == Part::GeomCircle::getClassTypeId()) {
|
||||
const Part::GeomCircle *circleSeg1 = static_cast<const Part::GeomCircle *>(geo1);
|
||||
const Part::GeomCircle *circleSeg2 = static_cast<const Part::GeomCircle *>(geo);
|
||||
GetCirclesMinimalDistance(circleSeg1, circleSeg2, p1, p2);
|
||||
}
|
||||
} else
|
||||
return;
|
||||
} else if (Constr->FirstPos != Sketcher::PointPos::none) {
|
||||
|
||||
Reference in New Issue
Block a user