Exemplo n.º 1
0
RS_Vector RS_Image::getNearestPointOnEntity(const RS_Vector& coord,
        bool onEntity, double* dist, RS_Entity** entity) const{

    if (entity!=NULL) {
        *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 within image
        if(dist!=NULL) *dist=0.;
        return coord;
    }
    RS_VectorSolutions points(4);

    RS_Line l[] =
        {
            RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
            RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
            RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
            RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
        };

    for (int i=0; i<4; ++i) {
        points.set(i, l[i].getNearestPointOnEntity(coord, onEntity));
    }

    return points.getClosest(coord, dist);
}
Exemplo n.º 2
0
/**
 * Selects all entities within the given area.
 *
 * @param select True to select, False to deselect the entities.
 */
void RS_EntityContainer::selectWindow(RS_Vector v1, RS_Vector v2,
                                      bool select, bool cross) {

    bool included;

    for (RS_Entity* e=firstEntity(RS2::ResolveNone);
            e!=NULL;
            e=nextEntity(RS2::ResolveNone)) {

        included = false;

        if (e->isVisible()) {
            if (e->isInWindow(v1, v2)) {
                //e->setSelected(select);
                included = true;
            } else if (cross==true) {
                RS_Line l[] =
                    {
                        RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))),
                        RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)),
                        RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))),
                        RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1))
                    };
                RS_VectorSolutions sol;

                if (e->isContainer()) {
                    RS_EntityContainer* ec = (RS_EntityContainer*)e;
                    for (RS_Entity* se=ec->firstEntity(RS2::ResolveAll);
                            se!=NULL && included==false;
                            se=ec->nextEntity(RS2::ResolveAll)) {

                        for (int i=0; i<4; ++i) {
                            sol = RS_Information::getIntersection(
                                      se, &l[i], true);
                            if (sol.hasValid()) {
                                included = true;
                                break;
                            }
                        }
                    }
                } else {
                    for (int i=0; i<4; ++i) {
                        sol = RS_Information::getIntersection(e, &l[i], true);
                        if (sol.hasValid()) {
                            included = true;
                            break;
                        }
                    }
                }
            }
        }

        if (included) {
            e->setSelected(select);
        }
    }
}
Exemplo n.º 3
0
RS_Vector RS_Image::getNearestDist(double distance,
                                   const RS_Vector& coord,
                                   double* dist) {

    RS_VectorSolutions corners = getCorners();
    RS_VectorSolutions points(4);

    RS_Line l[] =
        {
            RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
            RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
            RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
            RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
        };

    for (int i=0; i<4; ++i) {
        points.set(i, l[i].getNearestDist(distance, coord, dist));
    }

    return points.getClosest(coord, dist);
}
Exemplo n.º 4
0
double RS_Image::getDistanceToPoint(const RS_Vector& coord,
                                    RS_Entity** entity,
                                    RS2::ResolveLevel /*level*/,
                                                                        double /*solidDist*/) const{
    if (entity!=NULL) {
        *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 dist;
    double minDist = RS_MAXDOUBLE;

    RS_Line l[] =
        {
            RS_Line(NULL, RS_LineData(corners.get(0), corners.get(1))),
            RS_Line(NULL, RS_LineData(corners.get(1), corners.get(2))),
            RS_Line(NULL, RS_LineData(corners.get(2), corners.get(3))),
            RS_Line(NULL, RS_LineData(corners.get(3), corners.get(0)))
        };

    for (int i=0; i<4; ++i) {
        dist = l[i].getDistanceToPoint(coord, NULL);
        if (dist<minDist) {
            minDist = dist;
        }
    }

    return minDist;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
0
/**
 * Creates a dimensioning line (line with one, two or no arrows and a text).
 *
 * @param forceAutoText Automatically reposition the text label.
 */
void RS_Dimension::updateCreateDimensionLine(const RS_Vector& p1,
        const RS_Vector& p2, bool arrow1, bool arrow2, bool forceAutoText) {

    // general scale (DIMSCALE)
    double dimscale = getGeneralScale();
    // text height (DIMTXT)
    double dimtxt = getTextHeight()*dimscale;
    // text distance to line (DIMGAP)
    double dimgap = getDimensionLineGap()*dimscale;

    // length of dimension line:
    double distance = p1.distanceTo(p2);
    // arrow size:
    double arrowSize = getArrowSize()*dimscale;

    // do we have to put the arrows outside of the line?
    bool outsideArrows = (distance<arrowSize*2.5);

    // arrow angles:
    double arrowAngle1, arrowAngle2;

    // Create dimension line:
    RS_Line* dimensionLine = new RS_Line(this, RS_LineData(p1, p2));
    dimensionLine->setPen(RS_Pen(RS2::FlagInvalid));
    dimensionLine->setLayer(NULL);
    addEntity(dimensionLine);

    if (outsideArrows==false) {
        arrowAngle1 = dimensionLine->getAngle2();
        arrowAngle2 = dimensionLine->getAngle1();
    } else {
        arrowAngle1 = dimensionLine->getAngle1();
        arrowAngle2 = dimensionLine->getAngle2();

        // extend dimension line outside arrows
        RS_Vector dir;
        dir.setPolar(arrowSize*2, arrowAngle2);
        dimensionLine->setStartpoint(p1 + dir);
        dimensionLine->setEndpoint(p2 - dir);
    }
double dimtsz=getTickSize()*dimscale;
if(dimtsz < 0.01) {
    //display arrow
    // Arrows:
    RS_SolidData sd;
    RS_Solid* arrow;

    if (arrow1) {
        // arrow 1
        arrow = new RS_Solid(this, sd);
        arrow->shapeArrow(p1,
                          arrowAngle1,
                          arrowSize);
        arrow->setPen(RS_Pen(RS2::FlagInvalid));
        arrow->setLayer(NULL);
        addEntity(arrow);
    }

    if (arrow2) {
        // arrow 2:
        arrow = new RS_Solid(this, sd);
        arrow->shapeArrow(p2,
                          arrowAngle2,
                          arrowSize);
        arrow->setPen(RS_Pen(RS2::FlagInvalid));
        arrow->setLayer(NULL);
        addEntity(arrow);
    }
}else{
    //display ticks
    // Arrows:

    RS_Line* tick;
    RS_Vector tickVector;
    tickVector.setPolar(dimtsz,arrowAngle1 + M_PI*0.25); //tick is 45 degree away

    if (arrow1) {
        // tick 1
        tick = new RS_Line(this, p1-tickVector, p1+tickVector);
        tick->setPen(RS_Pen(RS2::FlagInvalid));
        tick->setLayer(NULL);
        addEntity(tick);
    }

    if (arrow2) {
        // tick 2:
        tick = new RS_Line(this, p2-tickVector, p2+tickVector);
        tick->setPen(RS_Pen(RS2::FlagInvalid));
        tick->setLayer(NULL);
        addEntity(tick);
    }
}
    // Text label:
    RS_MTextData textData;
    RS_Vector textPos;

        double dimAngle1 = dimensionLine->getAngle1();
        double textAngle;
        bool corrected=false;
        if (getAlignText())
            textAngle =0.0;
        else
            textAngle = RS_Math::makeAngleReadable(dimAngle1, true, &corrected);

    if (data.middleOfText.valid && !forceAutoText) {
        textPos = data.middleOfText;
    } else {
        textPos = dimensionLine->getMiddlePoint();

        if (!getAlignText()) {
            RS_Vector distV;

            // rotate text so it's readable from the bottom or right (ISO)
            // quadrant 1 & 4
            if (corrected) {
                distV.setPolar(dimgap + dimtxt/2.0, dimAngle1-M_PI/2.0);
            } else {
                distV.setPolar(dimgap + dimtxt/2.0, dimAngle1+M_PI/2.0);
            }

            // move text away from dimension line:
            textPos+=distV;
        }
        //// the next update should still be able to adjust this
        ////   auto text position. leave it invalid
                data.middleOfText = textPos;
    }

    textData = RS_MTextData(textPos,
                           dimtxt, 30.0,
                           RS_MTextData::VAMiddle,
                           RS_MTextData::HACenter,
                           RS_MTextData::LeftToRight,
                           RS_MTextData::Exact,
                           1.0,
                           getLabel(),
                           "standard",
                           textAngle);

    RS_MText* text = new RS_MText(this, textData);

    // move text to the side:
    RS_Vector distH;
    if (text->getUsedTextWidth()>distance) {
        distH.setPolar(text->getUsedTextWidth()/2.0
                       +distance/2.0+dimgap, textAngle);
        text->move(distH);
    }
    text->setPen(RS_Pen(RS2::FlagInvalid));
    text->setLayer(NULL);
    //horizontal text, split dimensionLine
    if (getAlignText()) {
        double w =text->getUsedTextWidth()/2+dimgap;
        double h = text->getUsedTextHeight()/2+dimgap;
        RS_Vector v1 = textPos - RS_Vector(w, h);
        RS_Vector v2 = textPos + RS_Vector(w, h);
        RS_Line l[] = {
            RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))),
            RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)),
            RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))),
            RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1))
        };
        RS_VectorSolutions sol1, sol2;
        int inters= 0;
        do {
            sol1 = RS_Information::getIntersection(dimensionLine, &(l[inters++]), true);
        } while (!sol1.hasValid() && inters < 4);
        if (!sol1.hasValid()) {
            do {
                sol2 = RS_Information::getIntersection(dimensionLine, &(l[inters++]), true);
            } while (!sol2.hasValid() && inters < 4);
        }
        //are text intersecting dimensionLine?
        if (sol1.hasValid() && sol2.hasValid()) {
            //yes, split dimension line
            RS_Line* dimensionLine2 = (RS_Line*)dimensionLine->clone();
            v1 = sol1.get(0);
            v2 = sol2.get(0);
            if (p1.distanceTo(v1) < p1.distanceTo(v2)) {
                dimensionLine->setEndpoint(v1);
                dimensionLine2->setStartpoint(v2);
            } else {
                dimensionLine->setEndpoint(v2);
                dimensionLine2->setStartpoint(v1);
            }
            addEntity(dimensionLine2);
        }
    }

    addEntity(text);
}
Exemplo n.º 7
0
bool RS_Solid::isInCrossWindow(const RS_Vector& v1,const RS_Vector& v2)const {
//    bool sol = false;
    RS_Vector vBL, vTR;
    RS_VectorSolutions sol;
//sort imput vectors to BottomLeft & TopRight
    if (v1.x<v2.x) {
        vBL.x = v1.x;
        vTR.x = v2.x;
    } else {
        vBL.x = v2.x;
        vTR.x = v1.x;
    }
    if (v1.y<v2.y) {
        vBL.y = v1.y;
        vTR.y = v2.y;
    } else {
        vBL.y = v2.y;
        vTR.y = v1.y;
    }
    //Check if is out of window
    if ( getMin().x > vTR.x || getMax().x < vBL.x
           || getMin().y > vTR.y || getMax().y < vBL.y) {
        return false;
    }
	std::vector<RS_Line> l;
	l.push_back(RS_Line(nullptr, RS_LineData(data.corner[0], data.corner[1])));
	l.push_back(RS_Line(nullptr, RS_LineData(data.corner[1], data.corner[2])));
    if (data.corner[3].valid) {
		l.push_back(RS_Line(nullptr, RS_LineData(data.corner[2], data.corner[3])));
		l.push_back(RS_Line(nullptr, RS_LineData(data.corner[3], data.corner[0])));
    } else {
		l.push_back(RS_Line(nullptr, RS_LineData(data.corner[2], data.corner[0])));
    }
    //Find crossing edge
    if (getMax().x > vBL.x && getMin().x < vBL.x) {//left
		RS_Line edge = RS_Line(nullptr, RS_LineData(vBL, RS_Vector(vBL.x, vTR.y)));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    if (getMax().x > vTR.x && getMin().x < vTR.x) {//right
		RS_Line edge = RS_Line(nullptr, RS_LineData(RS_Vector(vTR.x, vBL.y), vTR));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    if (getMax().y > vBL.y && getMin().y < vBL.y) {//bottom
		RS_Line edge = RS_Line(nullptr, RS_LineData(vBL, RS_Vector(vTR.x, vBL.y)));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    if(getMax().y > vTR.y && getMin().y < vTR.y) {//top
		RS_Line edge = RS_Line(nullptr, RS_LineData(RS_Vector(vBL.x, vTR.y), vTR));
		for(auto const& l0: l) {
			sol = RS_Information::getIntersection(&edge, &l0, true);
            if (sol.hasValid()) {
                return true;
            }
        }
    }
    return false;
}
Exemplo n.º 8
0
/**
 * Selects all circles (and arcs min. 3/4 circle) with same diameter and same layer,
 * in a window (v1, v2)
 * mosty used with CAM bores 
 *
 * @param e  Must be an circle or arc (min. 3/4 circle)
 */
void RS_Selection::selectCircles(RS_Entity* e, RS_Vector v1, RS_Vector v2 /*, bool inside=true */ ) 
{
   if (e==NULL) 
     return;
   
   if (!e->isAtomic()) 
     return;

   e->toggleSelected(); 
   
   // bool cross = v2.y > v1.y;
   
   bool cross = v1.x > v2.x;
   
   bool select = !e->isSelected();
   RS_AtomicEntity* ae = (RS_AtomicEntity*)e;
   double r_clicked = 0;
   RS_Layer* layer_clicked = 0;
   

   if (graphicView!=NULL) 
     graphicView->drawEntity(e);
   
   if (ae->rtti()==RS2::EntityArc || ae->rtti()==RS2::EntityCircle)
     {
	r_clicked = ae->getRadius();
	
	if (ae->rtti()==RS2::EntityArc)
	  if(ae->getAngleLength() < 4.66)   /* ca. 267 grad (knapp 3/4 kreis) */
	    {
	       r_clicked = 0;
	       RS_DIALOGFACTORY->commandMessage("selected arc has AngleLength < 4.66");
	    }
	
	layer_clicked = ae->getLayer();
     }   
   
   for (RS_Entity* en=container->firstEntity(); en!=NULL; en=container->nextEntity()) 
     {
	int included = 0;
	
	if (en!=NULL && en->isVisible() && 
	    en->isAtomic() && en->isSelected()!=select && 
	    (en->rtti()==RS2::EntityArc || en->rtti()==RS2::EntityCircle) &&

	    (en->getLayer()==NULL || en->getLayer()->isLocked()==false)) 
	  {
	     ae = (RS_AtomicEntity*)en;
	     
 
	     if(en->isInWindow(v1, v2))
	       included++;
	     
	     if (cross == true)
	       {
		 RS_Line l[] =
		   {
                        RS_Line(NULL, RS_LineData(v1, RS_Vector(v2.x, v1.y))),
                        RS_Line(NULL, RS_LineData(RS_Vector(v2.x, v1.y), v2)),
                        RS_Line(NULL, RS_LineData(v2, RS_Vector(v1.x, v2.y))),
                        RS_Line(NULL, RS_LineData(RS_Vector(v1.x, v2.y), v1))
		   };
                RS_VectorSolutions sol;

                if (ae->isContainer()) 
		    continue;
                 else
		    {
		       for (int i=0; i<4; ++i) 
			 {
			    sol = RS_Information::getIntersection(ae, &l[i], true);
			    if (sol.hasValid())
			      {
				 included++;
				 break;
			      }
			 }
		    }
	       }
	     
	     // -----------------------
	     
	     if(included)
	       {
		  
		  double rc = ae->getRadius();
		  
		  double rdiff = fabs (rc - r_clicked);
		  
		  if ((r_clicked > 0.000003)  &&  (0.000003 > rdiff) && (ae->getLayer() == layer_clicked))
		    {
		       if (graphicView!=NULL)
			 {
			    graphicView->deleteEntity(ae);
			 }
		       
		       ae->setSelected(select);
		       
		       if (graphicView!=NULL) 
			 {
			    graphicView->drawEntity(ae);
			 }
		    }
	       }
	  }
     }
   //std::cerr << "ende in  rs_selection.cpp \n";
}