Fix automatic creation of tangent constriants.

a. Use scale to calculate max distance
b. Consider only circle/arc that actually touch the newly created line
c. Use of arc angles correctly
d. Find nearest touch point (not nearest center)
e. some optimization
This commit is contained in:
Itai Nahshon 2014-08-23 03:20:28 +03:00 committed by wmayer
parent 6eeaae57b8
commit e9ea1e2727

View File

@ -200,17 +200,22 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
if (constr.Type != Sketcher::None)
suggestedConstraints.push_back(constr);
// Find if there are tangent constraints (currently arcs and circles)
// FIXME needs to consider when zooming out?
const double tangDeviation = 2.;
int tangId = Constraint::GeoUndef;
double smlTangDist = 1e15f;
// Do not consider if distance is more than that.
// Decrease this value when a candidate is found.
double tangDeviation = 0.1 * sketchgui->getScaleFactor();
// Get geometry list
const std::vector<Part::Geometry *> geomlist = sketchgui->getSketchObject()->getCompleteGeometry();
Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f); // Current cursor point
Base::Vector3d tmpDir(Dir.fX, Dir.fY, 0.f); // Direction of line
Base::Vector3d tmpStart(Pos.fX-Dir.fX, Pos.fY-Dir.fY, 0.f); // Start point
// Iterate through geometry
int i = 0;
for (std::vector<Part::Geometry *>::const_iterator it=geomlist.begin(); it != geomlist.end(); ++it, i++) {
@ -219,20 +224,21 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>((*it));
Base::Vector3d center = circle->getCenter();
Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
double radius = circle->getRadius();
Base::Vector3d projPnt(0.f, 0.f, 0.f);
projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
double projDist = projPnt.Length();
// ignore if no touch (use dot product)
if(tmpDir * (center-tmpPos) > 0 || tmpDir * (center-tmpStart) < 0)
continue;
if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation)) {
// Find if nearest
if (projDist < smlTangDist) {
tangId = i;
smlTangDist = projDist;
}
Base::Vector3d projPnt(0.f, 0.f, 0.f);
projPnt = projPnt.ProjToLine(center - tmpPos, tmpDir);
double projDist = std::abs(projPnt.Length() - radius);
// Find if nearest
if (projDist < tangDeviation) {
tangId = i;
tangDeviation = projDist;
}
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
@ -241,24 +247,26 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
Base::Vector3d center = arc->getCenter();
double radius = arc->getRadius();
// ignore if no touch (use dot product)
if(tmpDir * (center-tmpPos) > 0 || tmpDir * (center-tmpStart) < 0)
continue;
Base::Vector3d projPnt(0.f, 0.f, 0.f);
Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
projPnt = projPnt.ProjToLine(center - tmpPos, tmpDir);
double projDist = std::abs(projPnt.Length() - radius);
projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
double projDist = projPnt.Length();
if ( projDist < radius + tangDeviation && projDist > radius - tangDeviation) {
if (projDist < tangDeviation) {
double startAngle, endAngle;
arc->getRange(startAngle, endAngle);
projPnt += center;
double angle = atan2(projPnt.y, projPnt.x);
while(angle < startAngle)
angle += 2*D_PI; // Bring it to range of arc
// if the pnt is on correct side of arc and find if nearest
if ((angle > startAngle && angle < endAngle) &&
(projDist < smlTangDist) ) {
// if the point is on correct side of arc
if (angle <= endAngle) { // Now need to check only one side
tangId = i;
smlTangDist = projDist;
tangDeviation = projDist;
}
}
}