Ejemplo n.º 1
0
double RS_Image::getDistanceToPoint(const RS_Vector& coord,
                                    RS_Entity** entity,
                                    RS2::ResolveLevel /*level*/,
                                                                        double /*solidDist*/) const{
    if (entity) {
        *entity = const_cast<RS_Image*>(this);
    }

    RS_VectorSolutions corners = getCorners();

    //allow selecting image by clicking within images, bug#3464626
	if(containsPoint(coord)){
		//if coord is on image

		RS_SETTINGS->beginGroup("/Appearance");
		bool draftMode = (bool)RS_SETTINGS->readNumEntry("/DraftMode", 0);
		RS_SETTINGS->endGroup();
		if(!draftMode) return double(0.);
	}
    //continue to allow selecting by image edges
    double minDist = RS_MAXDOUBLE;

	for (size_t i = 0; i < corners.size(); ++i){
		size_t const j = (i+1)%corners.size();
		RS_Line const l{corners.get(i), corners.get(j)};
		double const dist = l.getDistanceToPoint(coord, nullptr);
		minDist = std::min(minDist, dist);
	}

    return minDist;
}
Ejemplo n.º 2
0
void RS_Image::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) {
	if (!(painter && view) || !img.get() || img->isNull())
		return;

    // erase image:
    //if (painter->getPen().getColor()==view->getBackground()) {
    //	RS_VectorSolutions sol = getCorners();
    //
    //}

	RS_Vector scale{view->toGuiDX(data.uVector.magnitude()),
								view->toGuiDY(data.vVector.magnitude())};
    double angle = data.uVector.angle();

	painter->drawImg(*img,
                     view->toGui(data.insertionPoint),
                     angle, scale);

    if (isSelected()) {
        RS_VectorSolutions sol = getCorners();
		for (size_t i = 0; i < sol.size(); ++i){
			size_t const j = (i+1)%sol.size();
			painter->drawLine(view->toGui(sol.get(i)), view->toGui(sol.get(j)));
		}
    }
}
Ejemplo n.º 3
0
RS_Vector RS_Line::prepareTrim(const RS_Vector& trimCoord,
                               const RS_VectorSolutions& trimSol) {
//prepare trimming for multiple intersections
    if ( ! trimSol.hasValid()) return(RS_Vector(false));
    if ( trimSol.getNumber() == 1 ) return(trimSol.get(0));
    auto&& vp0=trimSol.getClosest(trimCoord,NULL,0);

    double dr2=trimCoord.squaredTo(vp0);
    //the trim point found is closer to mouse location (trimCoord) than both end points, return this trim point
    if(dr2 < trimCoord.squaredTo(getStartpoint()) && dr2 < trimCoord.squaredTo(getEndpoint())) return vp0;
    //the closer endpoint to trimCoord
    RS_Vector vp1=(trimCoord.squaredTo(getStartpoint()) <= trimCoord.squaredTo(getEndpoint()))?getStartpoint():getEndpoint();

    //searching for intersection in the direction of the closer end point
    auto&& dvp1=vp1 - trimCoord;
    RS_VectorSolutions sol1;
    for(size_t i=0; i<trimSol.size(); i++){
        auto&& dvp2=trimSol.at(i) - trimCoord;
        if( RS_Vector::dotP(dvp1, dvp2) > RS_TOLERANCE) sol1.push_back(trimSol.at(i));
    }
    //if found intersection in direction, return the closest to trimCoord from it
    if(sol1.size()) return sol1.getClosest(trimCoord,NULL,0);

    //no intersection by direction, return previously found closest intersection
    return vp0;
}
Ejemplo n.º 4
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.º 5
0
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) {
	if (! (painter && view)) {
        return;
    }

    //only draw the visible portion of line
	LC_Rect const viewportRect{view->toGraph(0, 0),
				view->toGraph(view->getWidth(), view->getHeight())};
	RS_VectorSolutions endPoints(0);
	if (viewportRect.inArea(getStartpoint(), RS_TOLERANCE))
		 endPoints.push_back(getStartpoint());
	if (viewportRect.inArea(getEndpoint(), RS_TOLERANCE))
		 endPoints.push_back(getEndpoint());

	RS_EntityContainer ec(nullptr);
	ec.addRectangle(viewportRect.minP(), viewportRect.maxP());

	if (endPoints.size()<2){
		RS_VectorSolutions vpIts;
		for(auto p: ec) {
			auto const sol=RS_Information::getIntersection(this, p, true);
			for (auto const& vp: sol) {
				if (vpIts.getClosestDistance(vp) <= RS_TOLERANCE * 10.)
					continue;
				vpIts.push_back(vp);
			}
		}
		for (auto const& vp: vpIts) {
			if (endPoints.getClosestDistance(vp) <= RS_TOLERANCE * 10.)
				continue;
			endPoints.push_back(vp);
		}
	}

	if (endPoints.size()<2) return;

	if ((endPoints[0] - getStartpoint()).squared() >
			(endPoints[1] - getStartpoint()).squared() )
		std::swap(endPoints[0],endPoints[1]);

	RS_Vector pStart{view->toGui(endPoints.at(0))};
	RS_Vector pEnd{view->toGui(endPoints.at(1))};
    //    std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl;
	RS_Vector direction = pEnd-pStart;

	if (isConstruction(true) && direction.squared() > RS_TOLERANCE){
        //extend line on a construction layer to fill the whole view
		RS_VectorSolutions vpIts;
		for(auto p: ec) {
			auto const sol=RS_Information::getIntersection(this, p, false);
			for (auto const& vp: sol) {
				if (vpIts.getClosestDistance(vp) <= RS_TOLERANCE * 10.)
					continue;
				vpIts.push_back(vp);
			}
		}

		//draw construction lines up to viewport border
		switch (vpIts.size()) {
		case 2:
			// no need to sort intersections
			break;
		case 3:
		case 4: {
			// will use the inner two points
			size_t i{0};
			for (size_t j = 2; j < vpIts.size(); ++j) {
				if (viewportRect.inArea(vpIts.at(j), RS_TOLERANCE * 10.))
					std::swap(vpIts[j], vpIts[i++]);
			}
		}
			break;
		default:
			//should not happen
			return;
		}
		pStart=view->toGui(vpIts.get(0));
		pEnd=view->toGui(vpIts.get(1));
		direction=pEnd-pStart;
    }
    double  length=direction.magnitude();
    patternOffset -= length;
    if (( !isSelected() && (
              getPen().getLineType()==RS2::SolidLine ||
              view->getDrawingMode()==RS2::ModePreview)) ) {
        //if length is too small, attempt to draw the line, could be a potential bug
        painter->drawLine(pStart,pEnd);
        return;
    }
    //    double styleFactor = getStyleFactor(view);


    // Pattern:
    const RS_LineTypePattern* pat;
    if (isSelected()) {
//        styleFactor=1.;
        pat = &RS_LineTypePattern::patternSelected;
    } else {
        pat = view->getPattern(getPen().getLineType());
    }
	if (!pat) {
//        patternOffset -= length;
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Line::draw: Invalid line pattern");
        painter->drawLine(pStart,pEnd);
        return;
    }
//    patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength;
    if(length<=RS_TOLERANCE){
        painter->drawLine(pStart,pEnd);
        return; //avoid division by zero
    }
    direction/=length; //cos(angle), sin(angle)
    // Pen to draw pattern is always solid:
    RS_Pen pen = painter->getPen();

    pen.setLineType(RS2::SolidLine);
    painter->setPen(pen);

    // index counter
	size_t i;

    // pattern segment length:
    double patternSegmentLength = pat->totalLength;

    // create pattern:
	size_t const patnum=pat->num > 0?pat->num:0;
	std::vector<RS_Vector> dp(patnum);
	std::vector<double> ds(patnum, 0.);
    if (pat->num >0 ){
        double dpmm=static_cast<RS_PainterQt*>(painter)->getDpmm();
        for (i=0; i<pat->num; ++i) {
            //        ds[j]=pat->pattern[i] * styleFactor;
            //fixme, styleFactor support needed

            ds[i]=dpmm*pat->pattern[i];
			if (fabs(ds[i]) < 1. ) ds[i] = (ds[i]>=0.)?1.:-1.;
            dp[i] = direction*fabs(ds[i]);
        }
	} else {
        RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread");
        painter->drawLine(view->toGui(getStartpoint()),
                          view->toGui(getEndpoint()));
        return;
    }
    double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength;
    //    double total= patternOffset-patternSegmentLength;

	RS_Vector curP{pStart+direction*total};
	for (int j=0; total<length; j=(j+1)%i) {

        // line segment (otherwise space segment)
		double const t2=total+fabs(ds[j]);
		RS_Vector const& p3=curP+dp[j];
        if (ds[j]>0.0 && t2 > 0.0) {
            // drop the whole pattern segment line, for ds[i]<0:
            // trim end points of pattern segment line to line
			RS_Vector const& p1 =(total > -0.5)?curP:pStart;
			RS_Vector const& p2 =(t2<length+0.5)?p3:pEnd;
            painter->drawLine(p1,p2);
        }
        total=t2;
        curP=p3;
	}

}