/** construct a ellipse or hyperbola as the path of center of common tangent circles of this two given entities*/ LC_Quadratic::LC_Quadratic(const RS_AtomicEntity* circle0, const RS_AtomicEntity* circle1, bool mirror): m_mQuad(2,2) ,m_vLinear(2) ,m_bValid(false) { // DEBUG_HEADER if(!( circle0->isArcCircleLine() && circle1->isArcCircleLine())) { return; } if(circle1->rtti() != RS2::EntityLine) std::swap(circle0, circle1); if(circle0->rtti() == RS2::EntityLine) { //two lines RS_Line* line0=(RS_Line*) circle0; RS_Line* line1=(RS_Line*) circle1; auto centers=RS_Information::getIntersection(line0,line1); // DEBUG_HEADER if(centers.size()!=1) return; double angle=0.5*(line0->getAngle1()+line1->getAngle1()); m_bValid=true; m_bIsQuadratic=true; m_mQuad(0,0)=0.; m_mQuad(0,1)=0.5; m_mQuad(1,0)=0.5; m_mQuad(1,1)=0.; m_vLinear(0)=0.; m_vLinear(1)=0.; m_dConst=0.; rotate(angle); move(centers.get(0)); // DEBUG_HEADER // std::cout<<*this<<std::endl; return; } if(circle1->rtti() == RS2::EntityLine) { // DEBUG_HEADER //one line, one circle const RS_Line* line1=static_cast<const RS_Line*>(circle1); RS_Vector normal=line1->getNormalVector()*circle0->getRadius(); RS_Vector disp=line1->getNearestPointOnEntity(circle0->getCenter(), false)-circle0->getCenter(); if(normal.dotP(disp)>0.) normal *= -1.; if(mirror) normal *= -1.; RS_Line directrix{line1->getStartpoint()+normal, line1->getEndpoint()+normal}; LC_Quadratic lc0(&directrix,circle0->getCenter()); *this = lc0; return; m_mQuad=lc0.getQuad(); m_vLinear=lc0.getLinear(); m_bIsQuadratic=true; m_bValid=true; m_dConst=lc0.m_dConst; return; } //two circles double const f=(circle0->getCenter()-circle1->getCenter()).magnitude()*0.5; double const a=fabs(circle0->getRadius()+circle1->getRadius())*0.5; double const c=fabs(circle0->getRadius()-circle1->getRadius())*0.5; // DEBUG_HEADER // qDebug()<<"circle center to center distance="<<2.*f<<"\ttotal radius="<<2.*a; if(a<RS_TOLERANCE) return; RS_Vector center=(circle0->getCenter()+circle1->getCenter())*0.5; double angle=center.angleTo(circle0->getCenter()); if( f<a){ //ellipse double const ratio=sqrt(a*a - f*f)/a; RS_Vector const& majorP=RS_Vector{angle}*a; RS_Ellipse const ellipse{center,majorP,ratio,0.,0.,false}; auto const& lc0=ellipse.getQuadratic(); m_mQuad=lc0.getQuad(); m_vLinear=lc0.getLinear(); m_bIsQuadratic=lc0.isQuadratic(); m_bValid=lc0.isValid(); m_dConst=lc0.m_dConst; // DEBUG_HEADER // std::cout<<"ellipse: "<<*this; return; } // DEBUG_HEADER if(c<RS_TOLERANCE){ //two circles are the same radius //degenerate hypberbola: straight lines //equation xy = 0 m_bValid=true; m_bIsQuadratic=true; m_mQuad(0,0)=0.; m_mQuad(0,1)=0.5; m_mQuad(1,0)=0.5; m_mQuad(1,1)=0.; m_vLinear(0)=0.; m_vLinear(1)=0.; m_dConst=0.; rotate(angle); move(center); return; } //hyperbola // equation: x^2/c^2 - y^2/(f^2 -c ^2) = 1 // f: from hyperbola center to one circle center // c: half of difference of two circles double b2= f*f - c*c; m_bValid=true; m_bIsQuadratic=true; m_mQuad(0,0)=1./(c*c); m_mQuad(0,1)=0.; m_mQuad(1,0)=0.; m_mQuad(1,1)=-1./b2; m_vLinear(0)=0.; m_vLinear(1)=0.; m_dConst=-1.; rotate(angle); move(center); return; }