Sketcher: Implement symmetry with respect to a point constraint, aka midpoint constraint

This commit is contained in:
logari81 2012-11-29 22:46:11 +01:00
parent b6eec06fa3
commit afcaa8b980
8 changed files with 217 additions and 23 deletions

View File

@ -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"

View File

@ -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;

View File

@ -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 {

View File

@ -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)
{

View File

@ -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();

View File

@ -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)

View File

@ -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 &params);

View File

@ -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();