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:
parent
6eeaae57b8
commit
e9ea1e2727
|
@ -202,15 +202,20 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
|
||||||
suggestedConstraints.push_back(constr);
|
suggestedConstraints.push_back(constr);
|
||||||
|
|
||||||
// Find if there are tangent constraints (currently arcs and circles)
|
// 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;
|
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
|
// Get geometry list
|
||||||
const std::vector<Part::Geometry *> geomlist = sketchgui->getSketchObject()->getCompleteGeometry();
|
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
|
// Iterate through geometry
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (std::vector<Part::Geometry *>::const_iterator it=geomlist.begin(); it != geomlist.end(); ++it, i++) {
|
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));
|
const Part::GeomCircle *circle = dynamic_cast<const Part::GeomCircle *>((*it));
|
||||||
|
|
||||||
Base::Vector3d center = circle->getCenter();
|
Base::Vector3d center = circle->getCenter();
|
||||||
Base::Vector3d tmpPos(Pos.fX, Pos.fY, 0.f);
|
|
||||||
|
|
||||||
double radius = circle->getRadius();
|
double radius = circle->getRadius();
|
||||||
|
|
||||||
Base::Vector3d projPnt(0.f, 0.f, 0.f);
|
// ignore if no touch (use dot product)
|
||||||
projPnt = projPnt.ProjToLine(center - tmpPos, Base::Vector3d(Dir.fX, Dir.fY));
|
if(tmpDir * (center-tmpPos) > 0 || tmpDir * (center-tmpStart) < 0)
|
||||||
double projDist = projPnt.Length();
|
continue;
|
||||||
|
|
||||||
if ( (projDist < radius + tangDeviation ) && (projDist > radius - tangDeviation)) {
|
Base::Vector3d projPnt(0.f, 0.f, 0.f);
|
||||||
// Find if nearest
|
projPnt = projPnt.ProjToLine(center - tmpPos, tmpDir);
|
||||||
if (projDist < smlTangDist) {
|
double projDist = std::abs(projPnt.Length() - radius);
|
||||||
tangId = i;
|
|
||||||
smlTangDist = projDist;
|
// Find if nearest
|
||||||
}
|
if (projDist < tangDeviation) {
|
||||||
|
tangId = i;
|
||||||
|
tangDeviation = projDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
} else if ((*it)->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
|
||||||
|
@ -241,24 +247,26 @@ int DrawSketchHandler::seekAutoConstraint(std::vector<AutoConstraint> &suggested
|
||||||
Base::Vector3d center = arc->getCenter();
|
Base::Vector3d center = arc->getCenter();
|
||||||
double radius = arc->getRadius();
|
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 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));
|
if (projDist < tangDeviation) {
|
||||||
double projDist = projPnt.Length();
|
|
||||||
|
|
||||||
if ( projDist < radius + tangDeviation && projDist > radius - tangDeviation) {
|
|
||||||
double startAngle, endAngle;
|
double startAngle, endAngle;
|
||||||
arc->getRange(startAngle, endAngle);
|
arc->getRange(startAngle, endAngle);
|
||||||
|
|
||||||
projPnt += center;
|
|
||||||
double angle = atan2(projPnt.y, projPnt.x);
|
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 the point is on correct side of arc
|
||||||
if ((angle > startAngle && angle < endAngle) &&
|
if (angle <= endAngle) { // Now need to check only one side
|
||||||
(projDist < smlTangDist) ) {
|
|
||||||
tangId = i;
|
tangId = i;
|
||||||
smlTangDist = projDist;
|
tangDeviation = projDist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user