Sketcher: Implement symmetry with respect to a point constraint, aka midpoint constraint
This commit is contained in:
parent
b6eec06fa3
commit
afcaa8b980
|
@ -51,7 +51,7 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
int SecondIndex= Constraint::GeoUndef;
|
||||
int SecondPos = none;
|
||||
int ThirdIndex = Constraint::GeoUndef;
|
||||
//int ThirdPos = none;
|
||||
int ThirdPos = none;
|
||||
double Value = 0;
|
||||
// Note: In Python 2.x PyArg_ParseTuple prints a warning if a float is given but an integer is expected.
|
||||
// This means we must use a PyObject and check afterwards if it's a float or integer.
|
||||
|
@ -292,6 +292,21 @@ int ConstraintPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|||
}
|
||||
}
|
||||
}
|
||||
PyErr_Clear();
|
||||
|
||||
if (PyArg_ParseTuple(args, "siiiiii", &ConstraintType, &FirstIndex, &FirstPos, &SecondIndex, &SecondPos, &ThirdIndex, &ThirdPos)) {
|
||||
// ConstraintType, GeoIndex1, PosIndex1, GeoIndex2, PosIndex2, GeoIndex3, PosIndex3
|
||||
if (strcmp("Symmetric",ConstraintType) == 0 ) {
|
||||
this->getConstraintPtr()->Type = Symmetric;
|
||||
this->getConstraintPtr()->First = FirstIndex;
|
||||
this->getConstraintPtr()->FirstPos = (Sketcher::PointPos) FirstPos;
|
||||
this->getConstraintPtr()->Second = SecondIndex;
|
||||
this->getConstraintPtr()->SecondPos = (Sketcher::PointPos) SecondPos;
|
||||
this->getConstraintPtr()->Third = ThirdIndex;
|
||||
this->getConstraintPtr()->ThirdPos = (Sketcher::PointPos) ThirdPos;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_TypeError, "Constraint constructor accepts:\n"
|
||||
"-- empty parameter list\n"
|
||||
|
|
|
@ -537,8 +537,13 @@ int Sketch::addConstraint(const Constraint *constraint)
|
|||
rtn = addEqualConstraint(constraint->First,constraint->Second);
|
||||
break;
|
||||
case Symmetric:
|
||||
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos,constraint->Third);
|
||||
if (constraint->ThirdPos != none)
|
||||
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos,
|
||||
constraint->Third,constraint->ThirdPos);
|
||||
else
|
||||
rtn = addSymmetricConstraint(constraint->First,constraint->FirstPos,
|
||||
constraint->Second,constraint->SecondPos,constraint->Third);
|
||||
break;
|
||||
case None:
|
||||
break;
|
||||
|
@ -1522,6 +1527,30 @@ int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointP
|
|||
return -1;
|
||||
}
|
||||
|
||||
int Sketch::addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2,
|
||||
int geoId3, PointPos pos3)
|
||||
{
|
||||
geoId1 = checkGeoId(geoId1);
|
||||
geoId2 = checkGeoId(geoId2);
|
||||
geoId3 = checkGeoId(geoId3);
|
||||
|
||||
int pointId1 = getPointId(geoId1, pos1);
|
||||
int pointId2 = getPointId(geoId2, pos2);
|
||||
int pointId3 = getPointId(geoId3, pos3);
|
||||
|
||||
if (pointId1 >= 0 && pointId1 < int(Points.size()) &&
|
||||
pointId2 >= 0 && pointId2 < int(Points.size()) &&
|
||||
pointId3 >= 0 && pointId3 < int(Points.size())) {
|
||||
GCS::Point &p1 = Points[pointId1];
|
||||
GCS::Point &p2 = Points[pointId2];
|
||||
GCS::Point &p = Points[pointId3];
|
||||
int tag = ++ConstraintsCounter;
|
||||
GCSsys.addConstraintP2PSymmetric(p1, p2, p, tag);
|
||||
return ConstraintsCounter;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Sketch::updateGeometry()
|
||||
{
|
||||
int i=0;
|
||||
|
|
|
@ -172,6 +172,8 @@ public:
|
|||
int addPointOnObjectConstraint(int geoId1, PointPos pos1, int geoId2);
|
||||
/// add a symmetric constraint between two points with respect to a line
|
||||
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3);
|
||||
/// add a symmetric constraint between three points, the last point is in the middle of the first two
|
||||
int addSymmetricConstraint(int geoId1, PointPos pos1, int geoId2, PointPos pos2, int geoId3, PointPos pos3);
|
||||
//@}
|
||||
|
||||
enum GeoType {
|
||||
|
|
|
@ -413,6 +413,18 @@ ConstraintPointOnLine::ConstraintPointOnLine(Point &p, Line &l)
|
|||
rescale();
|
||||
}
|
||||
|
||||
ConstraintPointOnLine::ConstraintPointOnLine(Point &p, Point &lp1, Point &lp2)
|
||||
{
|
||||
pvec.push_back(p.x);
|
||||
pvec.push_back(p.y);
|
||||
pvec.push_back(lp1.x);
|
||||
pvec.push_back(lp1.y);
|
||||
pvec.push_back(lp2.x);
|
||||
pvec.push_back(lp2.y);
|
||||
origpvec = pvec;
|
||||
rescale();
|
||||
}
|
||||
|
||||
ConstraintType ConstraintPointOnLine::getTypeId()
|
||||
{
|
||||
return PointOnLine;
|
||||
|
@ -460,6 +472,74 @@ double ConstraintPointOnLine::grad(double *param)
|
|||
return scale * deriv;
|
||||
}
|
||||
|
||||
// PointOnPerpBisector
|
||||
ConstraintPointOnPerpBisector::ConstraintPointOnPerpBisector(Point &p, Line &l)
|
||||
{
|
||||
pvec.push_back(p.x);
|
||||
pvec.push_back(p.y);
|
||||
pvec.push_back(l.p1.x);
|
||||
pvec.push_back(l.p1.y);
|
||||
pvec.push_back(l.p2.x);
|
||||
pvec.push_back(l.p2.y);
|
||||
origpvec = pvec;
|
||||
rescale();
|
||||
}
|
||||
|
||||
ConstraintPointOnPerpBisector::ConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2)
|
||||
{
|
||||
pvec.push_back(p.x);
|
||||
pvec.push_back(p.y);
|
||||
pvec.push_back(lp1.x);
|
||||
pvec.push_back(lp1.y);
|
||||
pvec.push_back(lp2.x);
|
||||
pvec.push_back(lp2.y);
|
||||
origpvec = pvec;
|
||||
rescale();
|
||||
}
|
||||
|
||||
ConstraintType ConstraintPointOnPerpBisector::getTypeId()
|
||||
{
|
||||
return PointOnPerpBisector;
|
||||
}
|
||||
|
||||
void ConstraintPointOnPerpBisector::rescale(double coef)
|
||||
{
|
||||
scale = coef;
|
||||
}
|
||||
|
||||
double ConstraintPointOnPerpBisector::error()
|
||||
{
|
||||
double dx1 = *p1x() - *p0x();
|
||||
double dy1 = *p1y() - *p0y();
|
||||
double dx2 = *p2x() - *p0x();
|
||||
double dy2 = *p2y() - *p0y();
|
||||
return scale * (sqrt(dx1*dx1+dy1*dy1) - sqrt(dx2*dx2+dy2*dy2));
|
||||
}
|
||||
|
||||
double ConstraintPointOnPerpBisector::grad(double *param)
|
||||
{
|
||||
double deriv=0.;
|
||||
if (param == p0x() || param == p0y() ||
|
||||
param == p1x() || param == p1y()) {
|
||||
double dx1 = *p1x() - *p0x();
|
||||
double dy1 = *p1y() - *p0y();
|
||||
if (param == p0x()) deriv -= dx1/sqrt(dx1*dx1+dy1*dy1);
|
||||
if (param == p0y()) deriv -= dy1/sqrt(dx1*dx1+dy1*dy1);
|
||||
if (param == p1x()) deriv += dx1/sqrt(dx1*dx1+dy1*dy1);
|
||||
if (param == p1y()) deriv += dy1/sqrt(dx1*dx1+dy1*dy1);
|
||||
}
|
||||
if (param == p0x() || param == p0y() ||
|
||||
param == p2x() || param == p2y()) {
|
||||
double dx2 = *p2x() - *p0x();
|
||||
double dy2 = *p2y() - *p0y();
|
||||
if (param == p0x()) deriv += dx2/sqrt(dx2*dx2+dy2*dy2);
|
||||
if (param == p0y()) deriv += dy2/sqrt(dx2*dx2+dy2*dy2);
|
||||
if (param == p2x()) deriv -= dx2/sqrt(dx2*dx2+dy2*dy2);
|
||||
if (param == p2y()) deriv -= dy2/sqrt(dx2*dx2+dy2*dy2);
|
||||
}
|
||||
return scale * deriv;
|
||||
}
|
||||
|
||||
// Parallel
|
||||
ConstraintParallel::ConstraintParallel(Line &l1, Line &l2)
|
||||
{
|
||||
|
|
|
@ -41,11 +41,12 @@ namespace GCS
|
|||
P2PAngle = 4,
|
||||
P2LDistance = 5,
|
||||
PointOnLine = 6,
|
||||
Parallel = 7,
|
||||
Perpendicular = 8,
|
||||
L2LAngle = 9,
|
||||
MidpointOnLine = 10,
|
||||
TangentCircumf = 11
|
||||
PointOnPerpBisector = 7,
|
||||
Parallel = 8,
|
||||
Perpendicular = 9,
|
||||
L2LAngle = 10,
|
||||
MidpointOnLine = 11,
|
||||
TangentCircumf = 12
|
||||
};
|
||||
|
||||
class Constraint
|
||||
|
@ -171,6 +172,26 @@ namespace GCS
|
|||
inline double* p2y() { return pvec[5]; }
|
||||
public:
|
||||
ConstraintPointOnLine(Point &p, Line &l);
|
||||
ConstraintPointOnLine(Point &p, Point &lp1, Point &lp2);
|
||||
virtual ConstraintType getTypeId();
|
||||
virtual void rescale(double coef=1.);
|
||||
virtual double error();
|
||||
virtual double grad(double *);
|
||||
};
|
||||
|
||||
// PointOnPerpBisector
|
||||
class ConstraintPointOnPerpBisector : public Constraint
|
||||
{
|
||||
private:
|
||||
inline double* p0x() { return pvec[0]; }
|
||||
inline double* p0y() { return pvec[1]; }
|
||||
inline double* p1x() { return pvec[2]; }
|
||||
inline double* p1y() { return pvec[3]; }
|
||||
inline double* p2x() { return pvec[4]; }
|
||||
inline double* p2y() { return pvec[5]; }
|
||||
public:
|
||||
ConstraintPointOnPerpBisector(Point &p, Line &l);
|
||||
ConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2);
|
||||
virtual ConstraintType getTypeId();
|
||||
virtual void rescale(double coef=1.);
|
||||
virtual double error();
|
||||
|
|
|
@ -250,6 +250,27 @@ int System::addConstraintPointOnLine(Point &p, Line &l, int tagId)
|
|||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintPointOnLine(Point &p, Point &lp1, Point &lp2, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintPointOnLine(p, lp1, lp2);
|
||||
constr->setTag(tagId);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintPointOnPerpBisector(Point &p, Line &l, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintPointOnPerpBisector(p, l);
|
||||
constr->setTag(tagId);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintPointOnPerpBisector(p, lp1, lp2);
|
||||
constr->setTag(tagId);
|
||||
return addConstraint(constr);
|
||||
}
|
||||
|
||||
int System::addConstraintParallel(Line &l1, Line &l2, int tagId)
|
||||
{
|
||||
Constraint *constr = new ConstraintParallel(l1, l2);
|
||||
|
@ -552,6 +573,12 @@ int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId)
|
|||
return addConstraintMidpointOnLine(p1, p2, l.p1, l.p2, tagId);
|
||||
}
|
||||
|
||||
int System::addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId)
|
||||
{
|
||||
addConstraintPointOnPerpBisector(p, p1, p2, tagId);
|
||||
return addConstraintPointOnLine(p, p1, p2, tagId);
|
||||
}
|
||||
|
||||
void System::rescaleConstraint(int id, double coeff)
|
||||
{
|
||||
if (id >= clist.size() || id < 0)
|
||||
|
|
|
@ -99,6 +99,9 @@ namespace GCS
|
|||
int addConstraintP2PAngle(Point &p1, Point &p2, double *angle, int tagId=0);
|
||||
int addConstraintP2LDistance(Point &p, Line &l, double *distance, int tagId=0);
|
||||
int addConstraintPointOnLine(Point &p, Line &l, int tagId=0);
|
||||
int addConstraintPointOnLine(Point &p, Point &lp1, Point &lp2, int tagId=0);
|
||||
int addConstraintPointOnPerpBisector(Point &p, Line &l, int tagId=0);
|
||||
int addConstraintPointOnPerpBisector(Point &p, Point &lp1, Point &lp2, int tagId=0);
|
||||
int addConstraintParallel(Line &l1, Line &l2, int tagId=0);
|
||||
int addConstraintPerpendicular(Line &l1, Line &l2, int tagId=0);
|
||||
int addConstraintPerpendicular(Point &l1p1, Point &l1p2,
|
||||
|
@ -151,6 +154,7 @@ namespace GCS
|
|||
int addConstraintEqualRadius(Circle &c1, Arc &a2, int tagId=0);
|
||||
int addConstraintEqualRadius(Arc &a1, Arc &a2, int tagId=0);
|
||||
int addConstraintP2PSymmetric(Point &p1, Point &p2, Line &l, int tagId=0);
|
||||
int addConstraintP2PSymmetric(Point &p1, Point &p2, Point &p, int tagId=0);
|
||||
void rescaleConstraint(int id, double coeff);
|
||||
|
||||
void declareUnknowns(VEC_pD ¶ms);
|
||||
|
|
|
@ -1835,29 +1835,45 @@ void CmdSketcherConstrainSymmetric::activated(int iMsg)
|
|||
std::swap(PosId2,PosId3);
|
||||
}
|
||||
|
||||
if ((GeoId1 < 0 && GeoId2 < 0 && GeoId3 < 0)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a constraint between external geometries!"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVertex(GeoId1,PosId1) &&
|
||||
isVertex(GeoId2,PosId2) &&
|
||||
isEdge(GeoId3,PosId3)) {
|
||||
isVertex(GeoId2,PosId2)) {
|
||||
|
||||
if ((GeoId1 < 0 && GeoId2 < 0) || (GeoId1 < 0 && GeoId3 < 0) || (GeoId2 < 0 && GeoId3 < 0)) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a constraint between external geometries!"));
|
||||
return;
|
||||
}
|
||||
if (isEdge(GeoId3,PosId3)) {
|
||||
const Part::Geometry *geom = Obj->getGeometry(GeoId3);
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (GeoId1 == GeoId2 && GeoId2 == GeoId3) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a symmetry constraint between a line and its end points!"));
|
||||
return;
|
||||
}
|
||||
|
||||
const Part::Geometry *geom = Obj->getGeometry(GeoId3);
|
||||
if (geom->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
||||
if (GeoId1 == GeoId2 && GeoId2 == GeoId3) {
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
|
||||
QObject::tr("Cannot add a symmetry constraint between a line and its end points!"));
|
||||
// undo command open
|
||||
openCommand("add symmetric constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3);
|
||||
|
||||
// finish the transaction and update
|
||||
commitCommand();
|
||||
updateActive();
|
||||
|
||||
// clear the selection (convenience)
|
||||
getSelection().clearSelection();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
else if (isVertex(GeoId3,PosId3)) {
|
||||
// undo command open
|
||||
openCommand("add symmetric constraint");
|
||||
Gui::Command::doCommand(
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3);
|
||||
Doc,"App.ActiveDocument.%s.addConstraint(Sketcher.Constraint('Symmetric',%d,%d,%d,%d,%d,%d)) ",
|
||||
selection[0].getFeatName(),GeoId1,PosId1,GeoId2,PosId2,GeoId3,PosId3);
|
||||
|
||||
// finish the transaction and update
|
||||
commitCommand();
|
||||
|
|
Loading…
Reference in New Issue
Block a user