// ARC void Intersect::visit(Arc_CSPtr arc, const geo::Vector& line) { const geo::Coordinate nearest = line.nearestPointOnPath(arc->center()); double dist = arc->center().distanceTo(nearest); // special case: arc touches line (tangent): // TODO: We properly should add a tolorance here ?? if (fabs(dist - arc->radius()) < _tolerance) { _intersectionPoints.push_back(nearest); return; } const geo::Coordinate d = line.end() - line.start(); const double r = arc->radius(); const geo:: Coordinate delta = line.start() - arc->center(); const double d2 = d.squared(); //intersection // solution = p + t d; //| p -c+ t d|^2 = r^2 // |d|^2 t^2 + 2 (p-c).d t + |p-c|^2 -r^2 = 0 const double a1 = delta.dot(d); const double discriminant = a1 * a1 - d2 * (delta.squared() - r * r); if (discriminant < - _tolerance) { return; } else { const double t = sqrtf(fabs(discriminant)); //two intersections const geo::Coordinate c1(line.start() + d * (t - a1) / d2); const geo::Coordinate c2(line.start() - d * (t + a1) / d2); if (_method == Method::Any || (_method == Method::OnPath && arc->isCoordinateOnPath(c1) && line.isCoordinateOnPath(c1))) { _intersectionPoints.push_back(c1); } if (_method == Method::Any || (_method == Method::OnPath && arc->isCoordinateOnPath(c2) && line.isCoordinateOnPath(c2))) { _intersectionPoints.push_back(c2); } } }
Arc::Arc(const Arc_CSPtr other, bool sameID) : CADEntity(other->layer(), other->metaTypes()), geo::Arc(other->center(), other->radius(), other->startAngle(), other->endAngle()) { if (sameID) { this->setID(other->id()); } }