Fix 0000461: Sketcher: tangent constraint between two arcs/circles
This commit is contained in:
parent
343bc96bfe
commit
f0a6d25621
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user