Fix 0000461: Sketcher: tangent constraint between two arcs/circles

This commit is contained in:
logari81 2012-03-22 14:14:07 +01:00
parent 343bc96bfe
commit f0a6d25621
6 changed files with 245 additions and 29 deletions

View File

@ -836,8 +836,33 @@ int Sketch::addTangentConstraint(int geoId1, int geoId2)
GCSsys.addConstraintTangent(l, c, tag);
return ConstraintsCounter;
}
} else
Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n");
} else if (Geoms[geoId1].type == Circle) {
GCS::Circle &c = Circles[Geoms[geoId1].index];
if (Geoms[geoId2].type == Circle) {
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, c2, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, a, tag);
return ConstraintsCounter;
}
} else if (Geoms[geoId1].type == Arc) {
GCS::Arc &a = Arcs[Geoms[geoId1].index];
if (Geoms[geoId2].type == Circle) {
GCS::Circle &c = Circles[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(c, a, tag);
return ConstraintsCounter;
} else if (Geoms[geoId2].type == Arc) {
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangent(a, a2, tag);
return ConstraintsCounter;
}
}
return -1;
}
@ -850,8 +875,8 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
// 2) Line1, start/end/mid, Circle2
// 3) Line1, start/end/mid, Arc2
// 4) Arc1, start/end, Line2
// 5) Arc1, start/end, Circle2 (not implemented yet)
// 6) Arc1, start/end, Arc2 (not implemented yet)
// 5) Arc1, start/end, Circle2
// 6) Arc1, start/end, Arc2
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
@ -895,16 +920,24 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2)
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Arc) {
//GCS::Arcs &a2 = Arcs[Geoms[geoId2].index];
//GCSsys.addConstraintPointOnArc(p1, a2);
//GCSsys.addConstraintTangent(a1, a2);
Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n");
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
int tag = ++ConstraintsCounter;
GCSsys.addConstraintPointOnArc(p1, a2, tag);
GCSsys.addConstraintTangent(a1, a2, tag);
return ConstraintsCounter;
}
else if (Geoms[geoId2].type == Circle) {
//GCS::Circle &c2 = Circles[Geoms[geoId2].index];
//GCSsys.addConstraintPointOnCircle(p1, c2);
//GCSsys.addConstraintTangent(a1, c2);
Base::Console().Warning("Tangency constraints between circles and arcs are not implemented yet.\n");
GCS::Circle &c2 = Circles[Geoms[geoId2].index];
if (pos1 == start) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentCircle2Arc(c2, a1, tag);
return ConstraintsCounter;
}
else if (pos1 == end) {
int tag = ++ConstraintsCounter;
GCSsys.addConstraintTangentArc2Circle(a1, c2, tag);
return ConstraintsCounter;
}
}
}
return -1;
@ -917,7 +950,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
// 1) Line1, start/end/mid, Line2, start/end/mid
// 2) Line1, start/end/mid, Arc2, start/end
// 3) Arc1, start/end, Line2, start/end/mid (converted to case #2)
// 4) Arc1, start/end, Arc2, start/end (not implemented yet)
// 4) Arc1, start/end, Arc2, start/end
geoId1 = checkGeoId(geoId1);
geoId2 = checkGeoId(geoId2);
@ -970,7 +1003,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
GCSsys.addConstraintTangentLine2Arc(l1.p1, l1.p2, a2, tag);
return ConstraintsCounter;
}
else if (pos1 == mid) {
else if (pos1 == mid) { // FIXME: coincidence with midpoint of line??
int tag = ++ConstraintsCounter;
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
GCSsys.addConstraintTangent(l1, a2, tag);
@ -988,7 +1021,7 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
GCSsys.addConstraintTangentArc2Line(a2, l1.p2, l1.p1, tag);
return ConstraintsCounter;
}
else if (pos1 == mid) {
else if (pos1 == mid) { // FIXME: coincidence with midpoint of line??
int tag = ++ConstraintsCounter;
GCSsys.addConstraintP2PCoincident(p1, p2, tag);
GCSsys.addConstraintTangent(l1, a2, tag);
@ -1000,12 +1033,26 @@ int Sketch::addTangentConstraint(int geoId1, PointPos pos1, int geoId2, PointPos
}
}
else if (Geoms[geoId1].type == Arc) {
//GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
GCS::Arc &a1 = Arcs[Geoms[geoId1].index];
if (Geoms[geoId2].type == Arc) {
//GCS::Arcs &a2 = Arcs[Geoms[geoId2].index];
//GCSsys.addConstraintPointOnArc(p1, a2);
//GCSsys.addConstraintTangent(a1, a2);
Base::Console().Warning("Tangency constraints between arcs are not implemented yet.\n");
GCS::Arc &a2 = Arcs[Geoms[geoId2].index];
if (pos1 == start && (pos2 == start || pos2 == end)) {
int tag = ++ConstraintsCounter;
if (pos2 == start)
GCSsys.addConstraintTangentArc2Arc(a1, true, a2, false, tag);
else // if (pos2 == end)
GCSsys.addConstraintTangentArc2Arc(a1, true, a2, true, tag);
// GCSsys.addConstraintTangentArc2Arc(a2, false, a1, false, tag);
return ConstraintsCounter;
}
else if (pos1 == end && (pos2 == start || pos2 == end)) {
int tag = ++ConstraintsCounter;
if (pos2 == start)
GCSsys.addConstraintTangentArc2Arc(a1, false, a2, false, tag);
else // if (pos2 == end)
GCSsys.addConstraintTangentArc2Arc(a1, false, a2, true, tag);
return ConstraintsCounter;
}
}
}
return -1;

View File

@ -771,4 +771,64 @@ double ConstraintMidpointOnLine::grad(double *param)
return scale * deriv;
}
// TangentCircumf
ConstraintTangentCircumf::ConstraintTangentCircumf(Point &p1, Point &p2,
double *rad1, double *rad2, bool internal_)
{
internal = internal_;
pvec.push_back(p1.x);
pvec.push_back(p1.y);
pvec.push_back(p2.x);
pvec.push_back(p2.y);
pvec.push_back(rad1);
pvec.push_back(rad2);
origpvec = pvec;
rescale();
}
ConstraintType ConstraintTangentCircumf::getTypeId()
{
return TangentCircumf;
}
void ConstraintTangentCircumf::rescale(double coef)
{
scale = coef * 1;
}
double ConstraintTangentCircumf::error()
{
double dx = (*c1x() - *c2x());
double dy = (*c1y() - *c2y());
if (internal)
return scale * (sqrt(dx*dx + dy*dy) - std::abs(*r1() - *r2()));
else
return scale * (sqrt(dx*dx + dy*dy) - (*r1() + *r2()));
}
double ConstraintTangentCircumf::grad(double *param)
{
double deriv=0.;
if (param == c1x() || param == c1y() ||
param == c2x() || param == c2y()||
param == r1() || param == r2()) {
double dx = (*c1x() - *c2x());
double dy = (*c1y() - *c2y());
double d = sqrt(dx*dx + dy*dy);
if (param == c1x()) deriv += dx/d;
if (param == c1y()) deriv += dy/d;
if (param == c2x()) deriv += -dx/d;
if (param == c2y()) deriv += -dy/d;
if (internal) {
if (param == r1()) deriv += (*r1() > *r2()) ? -1 : 1;
if (param == r2()) deriv += (*r1() > *r2()) ? 1 : -1;
}
else {
if (param == r1()) deriv += -1;
if (param == r2()) deriv += -1;
}
}
return scale * deriv;
}
} //namespace GCS

View File

@ -44,7 +44,8 @@ namespace GCS
Parallel = 7,
Perpendicular = 8,
L2LAngle = 9,
MidpointOnLine = 10
MidpointOnLine = 10,
TangentCircumf = 11
};
class Constraint
@ -262,6 +263,26 @@ namespace GCS
virtual double grad(double *);
};
// TangentCircumf
class ConstraintTangentCircumf : public Constraint
{
private:
inline double* c1x() { return pvec[0]; }
inline double* c1y() { return pvec[1]; }
inline double* c2x() { return pvec[2]; }
inline double* c2y() { return pvec[3]; }
inline double* r1() { return pvec[4]; }
inline double* r2() { return pvec[5]; }
bool internal;
public:
ConstraintTangentCircumf(Point &p1, Point &p2,
double *rad1, double *rad2, bool internal_=false);
virtual ConstraintType getTypeId();
virtual void rescale(double coef=1.);
virtual double error();
virtual double grad(double *);
};
} //namespace GCS
#endif // FREEGCS_CONSTRAINTS_H

View File

@ -286,6 +286,14 @@ int System::addConstraintMidpointOnLine(Point &l1p1, Point &l1p2,
return addConstraint(constr);
}
int System::addConstraintTangentCircumf(Point &p1, Point &p2, double *rad1, double *rad2,
bool internal, int tagId)
{
Constraint *constr = new ConstraintTangentCircumf(p1, p2, rad1, rad2, internal);
constr->setTag(tagId);
return addConstraint(constr);
}
// derived constraints
int System::addConstraintP2PCoincident(Point &p1, Point &p2, int tagId)
@ -352,6 +360,33 @@ int System::addConstraintTangent(Line &l, Arc &a, int tagId)
return addConstraintP2LDistance(a.center, l, a.rad, tagId);
}
int System::addConstraintTangent(Circle &c1, Circle &c2, int tagId)
{
double dx = *(c2.center.x) - *(c1.center.x);
double dy = *(c2.center.y) - *(c1.center.y);
double d = sqrt(dx*dx + dy*dy);
return addConstraintTangentCircumf(c1.center, c2.center, c1.rad, c2.rad,
(d < *c1.rad || d < *c2.rad), tagId);
}
int System::addConstraintTangent(Arc &a1, Arc &a2, int tagId)
{
double dx = *(a2.center.x) - *(a1.center.x);
double dy = *(a2.center.y) - *(a1.center.y);
double d = sqrt(dx*dx + dy*dy);
return addConstraintTangentCircumf(a1.center, a2.center, a1.rad, a2.rad,
(d < *a1.rad || d < *a2.rad), tagId);
}
int System::addConstraintTangent(Circle &c, Arc &a, int tagId)
{
double dx = *(a.center.x) - *(c.center.x);
double dy = *(a.center.y) - *(c.center.y);
double d = sqrt(dx*dx + dy*dy);
return addConstraintTangentCircumf(c.center, a.center, c.rad, a.rad,
(d < *c.rad || d < *a.rad), tagId);
}
int System::addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId)
{
addConstraintP2PCoincident(p2, a.start, tagId);
@ -366,6 +401,43 @@ int System::addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId
return addConstraintP2PAngle(p1, p2, a.endAngle, incr_angle, tagId);
}
int System::addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId)
{
addConstraintPointOnCircle(a.start, c, tagId);
double dx = *(a.start.x) - *(c.center.x);
double dy = *(a.start.y) - *(c.center.y);
if (dx * cos(*(a.startAngle)) + dy * sin(*(a.startAngle)) > 0)
addConstraintP2PAngle(c.center, a.start, a.startAngle, 0, tagId);
else
addConstraintP2PAngle(c.center, a.start, a.startAngle, M_PI, tagId);
}
int System::addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId)
{
addConstraintPointOnCircle(a.end, c, tagId);
double dx = *(a.end.x) - *(c.center.x);
double dy = *(a.end.y) - *(c.center.y);
if (dx * cos(*(a.endAngle)) + dy * sin(*(a.endAngle)) > 0)
addConstraintP2PAngle(c.center, a.end, a.endAngle, 0, tagId);
else
addConstraintP2PAngle(c.center, a.end, a.endAngle, M_PI, tagId);
}
int System::addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2,
int tagId)
{
Point &p1 = reverse1 ? a1.start : a1.end;
Point &p2 = reverse2 ? a2.end : a2.start;
addConstraintP2PCoincident(p1, p2, tagId);
double *angle1 = reverse1 ? a1.startAngle : a1.endAngle;
double *angle2 = reverse2 ? a2.endAngle : a2.startAngle;
if (cos(*angle1) * cos(*angle2) + sin(*angle1) * sin(*angle2) > 0)
addConstraintEqual(angle1, angle2, tagId);
else
addConstraintP2PAngle(p2, a2.center, angle1, 0, tagId);
}
int System::addConstraintCircleRadius(Circle &c, double *radius, int tagId)
{
return addConstraintEqual(c.rad, radius, tagId);

View File

@ -101,6 +101,8 @@ namespace GCS
int addConstraintMidpointOnLine(Line &l1, Line &l2, int tagId=0);
int addConstraintMidpointOnLine(Point &l1p1, Point &l1p2, Point &l2p1, Point &l2p2,
int tagId=0);
int addConstraintTangentCircumf(Point &p1, Point &p2, double *rad1, double *rad2,
bool internal=false, int tagId=0);
// derived constraints
int addConstraintP2PCoincident(Point &p1, Point &p2, int tagId=0);
@ -115,8 +117,15 @@ namespace GCS
int addConstraintPointOnArc(Point &p, Arc &a, int tagId=0);
int addConstraintTangent(Line &l, Circle &c, int tagId=0);
int addConstraintTangent(Line &l, Arc &a, int tagId=0);
int addConstraintTangent(Circle &c1, Circle &c2, int tagId=0);
int addConstraintTangent(Arc &a1, Arc &a2, int tagId=0);
int addConstraintTangent(Circle &c, Arc &a, int tagId=0);
int addConstraintTangentLine2Arc(Point &p1, Point &p2, Arc &a, int tagId=0);
int addConstraintTangentArc2Line(Arc &a, Point &p1, Point &p2, int tagId=0);
int addConstraintTangentCircle2Arc(Circle &c, Arc &a, int tagId=0);
int addConstraintTangentArc2Circle(Arc &a, Circle &c, int tagId=0);
int addConstraintTangentArc2Arc(Arc &a1, bool reverse1, Arc &a2, bool reverse2,
int tagId=0);
int addConstraintCircleRadius(Circle &c, double *radius, int tagId=0);
int addConstraintArcRadius(Arc &a, double *radius, int tagId=0);
int addConstraintEqualLength(Line &l1, Line &l2, double *length, int tagId=0);

View File

@ -2153,24 +2153,31 @@ Restart:
const Part::GeomCircle *circle1 = dynamic_cast<const Part::GeomCircle *>(geo1);
const Part::GeomCircle *circle2 = dynamic_cast<const Part::GeomCircle *>(geo2);
// tangency between two cicles
Base::Vector3d dir = (circle2->getCenter() - circle1->getCenter()).Normalize();
pos = circle1->getCenter() + dir * circle1->getRadius();
relPos = dir * 1;
}
else if (geo2->getTypeId()== Part::GeomCircle::getClassTypeId()) {
std::swap(geo1,geo2);
}
if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId()) {
if (geo1->getTypeId()== Part::GeomCircle::getClassTypeId() &&
geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>(geo1);
if (geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo2);
// tangency between a circle and an arc
}
const Part::GeomArcOfCircle *arc = dynamic_cast<const Part::GeomArcOfCircle *>(geo2);
// tangency between a circle and an arc
Base::Vector3d dir = (arc->getCenter() - circle->getCenter()).Normalize();
pos = circle->getCenter() + dir * circle->getRadius();
relPos = dir * 1;
}
if (geo1->getTypeId()== Part::GeomArcOfCircle::getClassTypeId() &&
geo1->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
else if (geo1->getTypeId()== Part::GeomArcOfCircle::getClassTypeId() &&
geo2->getTypeId()== Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *arc1 = dynamic_cast<const Part::GeomArcOfCircle *>(geo1);
const Part::GeomArcOfCircle *arc2 = dynamic_cast<const Part::GeomArcOfCircle *>(geo2);
// tangency between two arcs
Base::Vector3d dir = (arc2->getCenter() - arc1->getCenter()).Normalize();
pos = arc1->getCenter() + dir * arc1->getRadius();
relPos = dir * 1;
}
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->abPos = SbVec3f(pos.x, pos.y, zConstr); //Absolute Reference
dynamic_cast<SoZoomTranslation *>(sep->getChild(1))->translation = SbVec3f(relPos.x, relPos.y, 0);