/** * @return One or two intersection points between given entities. */ RS_VectorSolutions RS_Information::getIntersectionArcArc(RS_Entity const* e1, RS_Entity const* e2) { RS_VectorSolutions ret; if (!(e1 && e2)) return ret; if(e1->rtti() != RS2::EntityArc && e1->rtti() != RS2::EntityCircle) return ret; if(e2->rtti() != RS2::EntityArc && e2->rtti() != RS2::EntityCircle) return ret; RS_Vector c1 = e1->getCenter(); RS_Vector c2 = e2->getCenter(); double r1 = e1->getRadius(); double r2 = e2->getRadius(); RS_Vector u = c2 - c1; // concentric if (u.magnitude()<1.0e-6) { return ret; } RS_Vector v = RS_Vector(u.y, -u.x); double s, t1, t2, term; s = 1.0/2.0 * ((r1*r1 - r2*r2)/(RS_Math::pow(u.magnitude(), 2.0)) + 1.0); term = (r1*r1)/(RS_Math::pow(u.magnitude(), 2.0)) - s*s; // no intersection: if (term<0.0) { ret = RS_VectorSolutions(); } // one or two intersections: else { t1 = sqrt(term); t2 = -sqrt(term); bool tangent = false; RS_Vector sol1 = c1 + u*s + v*t1; RS_Vector sol2 = c1 + u*s + v*t2; if (sol1.distanceTo(sol2)<1.0e-4) { sol2 = RS_Vector(false); ret = RS_VectorSolutions({sol1}); tangent = true; } else { ret = RS_VectorSolutions({sol1, sol2}); } ret.setTangent(tangent); } return ret; }
/** * @return One or two intersection points between given entities. */ RS_VectorSolutions RS_Information::getIntersectionLineArc(RS_Line* line, RS_Arc* arc) { RS_VectorSolutions ret; if (line==NULL || arc==NULL) { return ret; } double dist=0.0; RS_Vector nearest; nearest = line->getNearestPointOnEntity(arc->getCenter(), false, &dist); // special case: arc touches line (tangent): if (fabs(dist - arc->getRadius()) < 1.0e-4) { ret = RS_VectorSolutions(nearest); ret.setTangent(true); return ret; } RS_Vector p = line->getStartpoint(); RS_Vector d = line->getEndpoint() - line->getStartpoint(); if (d.magnitude()<1.0e-6) { return ret; } RS_Vector c = arc->getCenter(); double r = arc->getRadius(); RS_Vector delta = p - c; // root term: double term = RS_Math::pow(RS_Vector::dotP(d, delta), 2.0) - RS_Math::pow(d.magnitude(), 2.0) * (RS_Math::pow(delta.magnitude(), 2.0) - RS_Math::pow(r, 2.0)); // no intersection: if (term<0.0) { RS_VectorSolutions s; ret = s; } // one or two intersections: else { double t1 = (- RS_Vector::dotP(d, delta) + sqrt(term)) / RS_Math::pow(d.magnitude(), 2.0); double t2; bool tangent = false; // only one intersection: if (fabs(term)<RS_TOLERANCE) { t2 = t1; tangent = true; } // two intersections else { t2 = (-RS_Vector::dotP(d, delta) - sqrt(term)) / RS_Math::pow(d.magnitude(), 2.0); } RS_Vector sol1; RS_Vector sol2(false); sol1 = p + d * t1; if (!tangent) { sol2 = p + d * t2; } ret = RS_VectorSolutions(sol1, sol2); ret.setTangent(tangent); } return ret; }
/** * @return One or two intersection points between given entities. */ RS_VectorSolutions RS_Information::getIntersectionLineArc(RS_Line* line, RS_Arc* arc) { RS_VectorSolutions ret; if (!(line && arc)) return ret; double dist=0.0; RS_Vector nearest; nearest = line->getNearestPointOnEntity(arc->getCenter(), false, &dist); // special case: arc touches line (tangent): if (nearest.valid && fabs(dist - arc->getRadius()) < 1.0e-4) { ret = RS_VectorSolutions({nearest}); ret.setTangent(true); return ret; } RS_Vector p = line->getStartpoint(); RS_Vector d = line->getEndpoint() - line->getStartpoint(); double d2=d.squared(); RS_Vector c = arc->getCenter(); double r = arc->getRadius(); RS_Vector delta = p - c; if (d2<RS_TOLERANCE2) { //line too short, still check the whether the line touches the arc if ( fabs(delta.squared() - r*r) < 2.*RS_TOLERANCE*r ){ return RS_VectorSolutions({line->getMiddlePoint()}); } return ret; } //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 double a1 = RS_Vector::dotP(delta,d); double term1 = a1*a1 - d2*(delta.squared()-r*r); // std::cout<<" discriminant= "<<term1<<std::endl; if( term1 < - RS_TOLERANCE) { // std::cout<<"no intersection\n"; return ret; }else{ term1=fabs(term1); // std::cout<< "term1="<<term1 <<" threshold: "<< RS_TOLERANCE * d2 <<std::endl; if( term1 < RS_TOLERANCE * d2 ) { //tangential; // ret=RS_VectorSolutions(p - d*(a1/d2)); ret=RS_VectorSolutions({line->getNearestPointOnEntity(c, false)}); ret.setTangent(true); // std::cout<<"Tangential point: "<<ret<<std::endl; return ret; } double t = sqrt(fabs(term1)); //two intersections return RS_VectorSolutions({ p + d*(t-a1)/d2, p -d*(t+a1)/d2}); } // // root term: // term1 = r*r - delta.squared() + term1*term1/d.squared(); // double term = RS_Math::pow(RS_Vector::dotP(d, delta), 2.0) // - RS_Math::pow(d.magnitude(), 2.0) // * (RS_Math::pow(delta.magnitude(), 2.0) - RS_Math::pow(r, 2.0)); // std::cout<<"old term= "<<term<<"\tnew term= "<<term1<<std::endl; // // no intersection: // if (term<0.0) { // ret = RS_VectorSolutions() ; // } // // one or two intersections: // else { // double t1 = (- RS_Vector::dotP(d, delta) + sqrt(term)) // / RS_Math::pow(d.magnitude(), 2.0); // double t2; // bool tangent = false; // // only one intersection: // if (fabs(term)<RS_TOLERANCE) { // t2 = t1; // tangent = true; // } // // two intersections // else { // t2 = (-RS_Vector::dotP(d, delta) - sqrt(term)) // / RS_Math::pow(d.magnitude(), 2.0); // } // RS_Vector sol1; // RS_Vector sol2(false); // sol1 = p + d * t1; // if (!tangent) { // sol2 = p + d * t2; // } // ret = RS_VectorSolutions(sol1, sol2); // ret.setTangent(tangent); // } // std::cout<<"ret= "<<ret<<std::endl; // return ret; }