Sketcher : ArcLength Constraint
This commit is contained in:
committed by
Florian Foinant-Willig
parent
8ff81d8dfc
commit
ef35ec195d
@@ -2162,7 +2162,7 @@ int Sketch::addConstraint(const Constraint* constraint)
|
||||
c.driving);
|
||||
}
|
||||
}
|
||||
else { // line length
|
||||
else { // line length, arc length
|
||||
c.value = new double(constraint->getValue());
|
||||
if (c.driving) {
|
||||
FixParameters.push_back(c.value);
|
||||
@@ -3288,19 +3288,23 @@ int Sketch::addAngleAtPointConstraint(int geoId1,
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
|
||||
// line length constraint
|
||||
// line length and arc length constraint
|
||||
int Sketch::addDistanceConstraint(int geoId, double* value, bool driving)
|
||||
{
|
||||
geoId = checkGeoId(geoId);
|
||||
|
||||
if (Geoms[geoId].type != Line) {
|
||||
int tag = ++ConstraintsCounter;
|
||||
if (Geoms[geoId].type == Line) {
|
||||
GCS::Line& l = Lines[Geoms[geoId].index];
|
||||
GCSsys.addConstraintP2PDistance(l.p1, l.p2, value, tag, driving);
|
||||
}
|
||||
else if (Geoms[geoId].type == Arc) {
|
||||
GCS::Arc& a = Arcs[Geoms[geoId].index];
|
||||
GCSsys.addConstraintArcLength(a, value, tag, driving);
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
GCS::Line& l = Lines[Geoms[geoId].index];
|
||||
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PDistance(l.p1, l.p2, value, tag, driving);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#pragma warning(disable : 4251)
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <algorithm>
|
||||
#define DEBUG_DERIVS 0
|
||||
#if DEBUG_DERIVS
|
||||
@@ -3491,4 +3493,90 @@ double ConstraintP2CDistance::grad(double* param)
|
||||
return deriv * scale;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------
|
||||
// ConstraintArcLength
|
||||
ConstraintArcLength::ConstraintArcLength(Arc& a, double* d)
|
||||
{
|
||||
this->d = d;
|
||||
pvec.push_back(d);
|
||||
|
||||
this->arc = a;
|
||||
this->arc.PushOwnParams(pvec);
|
||||
|
||||
origpvec = pvec;
|
||||
pvecChangedFlag = true;
|
||||
rescale();
|
||||
}
|
||||
|
||||
void ConstraintArcLength::ReconstructGeomPointers()
|
||||
{
|
||||
int i = 0;
|
||||
i++; // skip the first parameter as there is the inline function distance for it
|
||||
arc.ReconstructOnNewPvec(pvec, i);
|
||||
pvecChangedFlag = false;
|
||||
}
|
||||
|
||||
ConstraintType ConstraintArcLength::getTypeId()
|
||||
{
|
||||
return ArcLength;
|
||||
}
|
||||
|
||||
void ConstraintArcLength::rescale(double coef)
|
||||
{
|
||||
scale = coef;
|
||||
}
|
||||
|
||||
void ConstraintArcLength::errorgrad(double* err, double* grad, double* param)
|
||||
{
|
||||
if (pvecChangedFlag) {
|
||||
ReconstructGeomPointers();
|
||||
}
|
||||
|
||||
double rad = *arc.rad;
|
||||
double endA = *arc.endAngle;
|
||||
double startA = *arc.startAngle;
|
||||
// Assume positive angles and CCW arc
|
||||
while (startA < 0.) {
|
||||
startA += 2. * M_PI;
|
||||
}
|
||||
while (endA < startA) {
|
||||
endA += 2. * M_PI;
|
||||
}
|
||||
if (err) {
|
||||
*err = rad * (endA - startA) - *distance();
|
||||
}
|
||||
else if (grad) {
|
||||
if (param == distance()) {
|
||||
// if constraint is not driving it varies on distance().
|
||||
*grad = -1.;
|
||||
}
|
||||
else {
|
||||
double dRad = param == arc.rad ? 1. : 0.;
|
||||
double dStartA = param == arc.startAngle ? 1. : 0.;
|
||||
double dEndA = param == arc.endAngle ? 1. : 0.;
|
||||
*grad = rad * (dEndA - dStartA) + dRad * (endA - startA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double ConstraintArcLength::error()
|
||||
{
|
||||
double err;
|
||||
errorgrad(&err, nullptr, nullptr);
|
||||
return scale * err;
|
||||
}
|
||||
|
||||
double ConstraintArcLength::grad(double* param)
|
||||
{
|
||||
if (findParamInPvec(param) == -1) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double deriv;
|
||||
errorgrad(nullptr, &deriv, param);
|
||||
|
||||
return deriv * scale;
|
||||
}
|
||||
|
||||
|
||||
} // namespace GCS
|
||||
|
||||
@@ -81,7 +81,8 @@ enum ConstraintType
|
||||
P2CDistance = 32,
|
||||
AngleViaPointAndParam = 33,
|
||||
AngleViaPointAndTwoParams = 34,
|
||||
AngleViaTwoPoints = 35
|
||||
AngleViaTwoPoints = 35,
|
||||
ArcLength = 36,
|
||||
};
|
||||
|
||||
enum InternalAlignmentType
|
||||
@@ -1385,6 +1386,28 @@ public:
|
||||
double grad(double*) override;
|
||||
};
|
||||
|
||||
// ArcLength
|
||||
class ConstraintArcLength: public Constraint
|
||||
{
|
||||
private:
|
||||
Arc arc;
|
||||
double* d;
|
||||
inline double* distance()
|
||||
{
|
||||
return pvec[0];
|
||||
}
|
||||
void ReconstructGeomPointers(); // writes pointers in pvec to the parameters of a
|
||||
void
|
||||
errorgrad(double* err,
|
||||
double* grad,
|
||||
double* param); // error and gradient combined. Values are returned through pointers.
|
||||
public:
|
||||
ConstraintArcLength(Arc& a, double* d);
|
||||
ConstraintType getTypeId() override;
|
||||
void rescale(double coef = 1.) override;
|
||||
double error() override;
|
||||
double grad(double*) override;
|
||||
};
|
||||
|
||||
} // namespace GCS
|
||||
|
||||
|
||||
@@ -889,6 +889,15 @@ int System::addConstraintP2CDistance(Point& p, Circle& c, double* distance, int
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintArcLength(Arc& a, double* distance, int tagId, bool driving)
|
||||
{
|
||||
Constraint* constr = new ConstraintArcLength(a, distance);
|
||||
constr->setTag(tagId);
|
||||
constr->setDriving(driving);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
|
||||
// derived constraints
|
||||
|
||||
int System::addConstraintP2PCoincident(Point& p1, Point& p2, int tagId, bool driving)
|
||||
|
||||
@@ -462,6 +462,7 @@ public:
|
||||
double* distance,
|
||||
int tagId = 0,
|
||||
bool driving = true);
|
||||
int addConstraintArcLength(Arc& a, double* dist, int tagId, bool driving = true);
|
||||
|
||||
// internal alignment constraints
|
||||
int addConstraintInternalAlignmentPoint2Ellipse(Ellipse& e,
|
||||
|
||||
@@ -243,6 +243,7 @@ public:
|
||||
double* startAngle;
|
||||
double* endAngle;
|
||||
// double *rad; //inherited
|
||||
// start and end points are computed by an ArcRules constraint
|
||||
Point start;
|
||||
Point end;
|
||||
// Point center; //inherited
|
||||
|
||||
@@ -4615,6 +4615,33 @@ void CmdSketcherConstrainDistance::activated(int iMsg)
|
||||
finishDatumConstraint(this, Obj, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else if (isArcOfCircle(*geom)) {
|
||||
auto arc = static_cast<const Part::GeomArcOfCircle*>(geom);
|
||||
double ActLength = arc->getAngle(false) * arc->getRadius();
|
||||
|
||||
openCommand(QT_TRANSLATE_NOOP("Command", "Add length constraint"));
|
||||
Gui::cmdAppObjectArgs(selection[0].getObject(),
|
||||
"addConstraint(Sketcher.Constraint('Distance',%d,%f))",
|
||||
GeoId1,
|
||||
ActLength);
|
||||
|
||||
// it is a constraint on a external line, make it non-driving
|
||||
if (arebothpointsorsegmentsfixed || GeoId1 <= Sketcher::GeoEnum::RefExt
|
||||
|| constraintCreationMode == Reference) {
|
||||
const std::vector<Sketcher::Constraint*>& ConStr = Obj->Constraints.getValues();
|
||||
|
||||
Gui::cmdAppObjectArgs(selection[0].getObject(),
|
||||
"setDriving(%d,%s)",
|
||||
ConStr.size() - 1,
|
||||
"False");
|
||||
finishDatumConstraint(this, Obj, false);
|
||||
}
|
||||
else {
|
||||
finishDatumConstraint(this, Obj, true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user