Ejemplo n.º 1
0
RS_VectorSolutions RS_Ellipse::getRefPoints() {
    RS_VectorSolutions ret;
    if(isArc()){
        //no start/end point for whole ellipse
        ret.push_back(getStartpoint());
        ret.push_back(getEndpoint());
    }
    ret.push_back(data.center);
    ret.appendTo(getFoci());
    return ret;
}
Ejemplo n.º 2
0
/**
  * create a circle of radius r and tangential to two given entities
  */
RS_VectorSolutions RS_Circle::createTan2(const QVector<RS_AtomicEntity*>& circles, const double& r)
{
    if(circles.size()<2) return false;
    auto&& e0=circles[0]->offsetTwoSides(r);
    auto&& e1=circles[1]->offsetTwoSides(r);
    RS_VectorSolutions centers;
    if(e0.size()>0 && e1.size()>=0) {
        for(auto it0=e0.begin();it0!=e0.end();it0++){
            for(auto it1=e1.begin();it1!=e1.end();it1++){
                centers.appendTo(RS_Information::getIntersection(*it0,*it1));
            }
        }
    }
    for(auto it0=e0.begin();it0!=e0.end();it0++){
        delete *it0;
    }
    for(auto it0=e1.begin();it0!=e1.end();it0++){
        delete *it0;
    }
    return centers;

}
Ejemplo n.º 3
0
bool RS_ActionDrawCircleTan3::getData(){
    if(getStatus() != SetCircle3) return false;
    //find the nearest circle
    int i=0;
    for(;i<circles.size();++i)
        if(circles[i]->rtti() == RS2::EntityLine) break;
    candidates.clear();
        const int i1=(i+1)%3;
        const int i2=(i+2)%3;
        if(i<circles.size() && circles[i]->rtti() == RS2::EntityLine){

            LC_Quadratic lc0(circles[i],circles[i1],false);
             LC_Quadratic lc01(circles[i],circles[i1],true);
            LC_Quadratic lc1;
            RS_VectorSolutions sol;
            //detect degenerate case two circles with the same radius
            if(circles[i1]->rtti()== RS2::EntityCircle &&
                    circles[i2]->rtti()== RS2::EntityCircle
                    ){
                RS_Circle* c1=static_cast<RS_Circle*>(circles[i1]);
                RS_Circle* c2=static_cast<RS_Circle*>(circles[i2]);
                if(fabs(fabs(c1->getRadius())-fabs(c2->getRadius()))<RS_TOLERANCE){
                    //degenerate
                    const RS_Vector p0=(c1->getCenter()+c2->getCenter())*0.5;
                    const RS_Vector p1=p0 + (c1->getCenter() - p0).rotate(0.5*M_PI);
                    lc1=RS_Line(NULL, RS_LineData(p0,p1 )).getQuadratic();
                    sol=LC_Quadratic::getIntersection(lc0,lc1);

                    sol.appendTo(LC_Quadratic::getIntersection(lc01,lc1));
                    lc1=RS_Line(NULL, RS_LineData(c1->getCenter(),c1->getCenter())).getQuadratic();
                    sol.appendTo(LC_Quadratic::getIntersection(lc0,lc1));
                    sol.appendTo(LC_Quadratic::getIntersection(lc01,lc1));
                }

            }
            if(sol.size()==0) {
                switch(circles[i2]->rtti()){
                case RS2::EntityCircle:
                    lc1=LC_Quadratic(circles[i],circles[i2], true);
                    sol.appendTo(LC_Quadratic::getIntersection(lc01,lc1));
                    if(circles[i1]->rtti()== RS2::EntityCircle )
                        sol.appendTo(LC_Quadratic::getIntersection(lc01,lc1));
                    //there's no break, because the default part would be run for circles as well
                default:
                    lc1=LC_Quadratic(circles[i],circles[i2]);
                    sol.appendTo(LC_Quadratic::getIntersection(lc01,lc1));
                    if(circles[i1]->rtti()== RS2::EntityCircle )
                        sol.appendTo(LC_Quadratic::getIntersection(lc01,lc1));
                }
            }
            double d;

        //line passes circle center, need a second parabola as the image of the line
        for(int j=1;j<=2;j++){
            if(circles[(i+j)%3]->rtti() == RS2::EntityCircle){
                circles[i]->getNearestPointOnEntity(circles[(i+j)%3]->getCenter(),
                                                    false,&d);
                if(d<RS_TOLERANCE) {
                    LC_Quadratic lc2(circles[i],circles[(i+j)%3], true);
                    sol.appendTo(LC_Quadratic::getIntersection(lc2,lc1));
                }
            }
        }

        //clean up duplicate and invalid
        RS_VectorSolutions sol1;
        for(size_t j=0; j<sol.size(); ++j){
            const RS_Vector&& vp=sol.at(j);
            if(vp.magnitude()>RS_MAXDOUBLE) continue;
            if(sol1.size())
                if(sol1.getClosestDistance(vp)<RS_TOLERANCE) continue;

            sol1.push_back(vp);
        }


        for(size_t j=0;j<sol1.size();j++){
            circles[i]->getNearestPointOnEntity(sol1[j],false,&d);
            RS_CircleData data(sol1[j],d);
            if(circles[(i+1)%3]->isTangent(data)==false) continue;
            if(circles[(i+2)%3]->isTangent(data)==false) continue;
            candidates<<RS_Circle(NULL,data);
        }
    }else{
        RS_Circle c(NULL,cData);
        candidates=c.createTan3(circles);
    }
    valid = ( candidates.size() >0);
    return valid;
}
Ejemplo n.º 4
0
bool RS_ActionDrawCircleTan3::getData(){
	if(getStatus() != SetCircle3) return false;
	//find the nearest circle
	size_t i=0;
	size_t const countLines=std::count_if(circles.begin(), circles.end(), [](RS_AtomicEntity* e)->bool
	{
			return e->rtti()==RS2::EntityLine;
});

	for(;i<circles.size();++i)
		if(circles[i]->rtti() == RS2::EntityLine) break;
	candidates.clear();
	size_t i1=(i+1)%3;
	size_t i2=(i+2)%3;
	if(i<circles.size() && circles[i]->rtti() == RS2::EntityLine){
		//one or more lines

		LC_Quadratic lc0(circles[i],circles[i1],false);
		LC_Quadratic lc1;
		RS_VectorSolutions sol;
		//detect degenerate case two circles with the same radius
		switch(countLines){
		default:
		case 0:
			//this should not happen
			assert(false);
		case 1:
			//1 line, two circles
		{
			for(unsigned k=0; k<4; ++k){
				//loop through all mirroring cases
				lc1=LC_Quadratic(circles[i],circles[i1], k & 1u);
				LC_Quadratic lc2=LC_Quadratic(circles[i],circles[i2], k & 2u);
				sol.appendTo(LC_Quadratic::getIntersection(lc1,lc2));
			}

		}
			break;
		case 2:
			//2 lines, one circle
		{
			if(circles[i2]->rtti()==RS2::EntityLine){
				std::swap(i1, i2);
			}
			//i2 is circle

			for(unsigned k=0; k<4; ++k){
				//loop through all mirroring cases
				lc1=LC_Quadratic(circles[i2],circles[i], k & 1u);
				LC_Quadratic lc2=LC_Quadratic(circles[i2],circles[i1], k & 2u);
				sol.appendTo(LC_Quadratic::getIntersection(lc1,lc2));
			}
		}
			break;
		case 3:
			//3 lines
		{
			lc0=circles[i]->getQuadratic();
			lc1=circles[i1]->getQuadratic();
			auto lc2=circles[i2]->getQuadratic();
			//attempt to have intersections (lc0, lc1), (lc0, lc2)
			auto sol1=LC_Quadratic::getIntersection(lc0,lc1);
			if(sol1.size()<1) {
				std::swap(lc0, lc2);
				std::swap(i, i2);
			}
			sol1=LC_Quadratic::getIntersection(lc0,lc2);
			if(sol1.size()<1) {
				std::swap(lc0, lc1);
				std::swap(i, i1);
			}

			RS_Line* line0=static_cast<RS_Line*>(circles[i]);
			RS_Line* line1=static_cast<RS_Line*>(circles[i1]);
			RS_Line* line2=static_cast<RS_Line*>(circles[i2]);
			lc0=line0->getQuadratic();
			lc1=line1->getQuadratic();
			lc2=line2->getQuadratic();
			//intersection 0, 1
			sol1=LC_Quadratic::getIntersection(lc0,lc1);
			if(!sol1.size()) {
				return false;
			}
			RS_Vector const v1=sol1.at(0);
			double angle1=0.5*(line0->getAngle1()+line1->getAngle1());

			//intersection 0, 2
			sol1=LC_Quadratic::getIntersection(lc0,lc2);
			double angle2;
			if(sol1.size()<1) {
				return false;
			}
			angle2=0.5*(line0->getAngle1()+line2->getAngle1());
			RS_Vector const& v2=sol1.at(0);
			//two bisector lines per intersection
			for(unsigned j=0; j<2; ++j){
				RS_Line l1{v1, v1+RS_Vector{angle1}};
				for(unsigned j1=0; j1<2; ++j1){
					RS_Line l2{v2, v2+RS_Vector{angle2}};
					sol.appendTo(RS_Information::getIntersectionLineLine(&l1, &l2));
					angle2 += M_PI_2;
				}
				angle1 += M_PI_2;
			}
		}
		}

		double d;

		//line passes circle center, need a second parabola as the image of the line
		for(int j=1;j<=2;j++){
			if(circles[(i+j)%3]->rtti() == RS2::EntityCircle){
				circles[i]->getNearestPointOnEntity(circles[(i+j)%3]->getCenter(),
						false,&d);
				if(d<RS_TOLERANCE) {
					LC_Quadratic lc2(circles[i],circles[(i+j)%3], true);
					sol.appendTo(LC_Quadratic::getIntersection(lc2,lc1));
				}
			}
		}

		//clean up duplicate and invalid
		RS_VectorSolutions sol1;
		for(const RS_Vector& vp: sol){
			if(vp.magnitude()>RS_MAXDOUBLE) continue;
			if(sol1.size() && sol1.getClosestDistance(vp)<RS_TOLERANCE) continue;
			sol1.push_back(vp);
		}

		for(auto const& v: sol1){
			circles[i]->getNearestPointOnEntity(v,false,&d);
			std::shared_ptr<RS_CircleData> data(new RS_CircleData(v,d));
			if(circles[(i+1)%3]->isTangent(*data)==false) continue;
			if(circles[(i+2)%3]->isTangent(*data)==false) continue;
			candidates.push_back(data);
		}

	}else{
        RS_Circle c(nullptr,*cData);
		auto solutions=c.createTan3(circles);
		candidates.clear();
		for(const RS_Circle& s: solutions){
			candidates.push_back(std::make_shared<RS_CircleData>(s.getData()));
		}
	}
	valid = ( candidates.size() >0);
	return valid;
}