예제 #1
0
QVector<RS_Entity* > RS_Circle::offsetTwoSides(const double& distance) const
{
    QVector<RS_Entity*> ret(0,NULL);
    ret<<new RS_Circle(NULL,RS_CircleData(getCenter(),getRadius()+distance));
    if(getRadius()>distance)
    ret<<new RS_Circle(NULL,RS_CircleData(getCenter(),getRadius()-distance));
    return ret;
}
예제 #2
0
QList<RS_Circle> RS_Circle::createTan3(const QVector<RS_AtomicEntity*>& circles)
{
    QList<RS_Circle> ret;
    if(circles.size()!=3) return ret;
     QList<RS_Circle> cs;
     for(unsigned short i=0;i<3;i++){
         cs<<RS_Circle(NULL,RS_CircleData(circles.at(i)->getCenter(),circles.at(i)->getRadius()));
     }
    unsigned short flags=0;
    do{
        ret.append(solveAppolloniusSingle(cs));
        flags++;
        unsigned short j=0;
        for(unsigned short i=1u;i<=4u;i<<=1){
            if(flags & i) {
                cs[j].setRadius( - fabs(cs[j].getRadius()));
            }else{
                cs[j].setRadius( fabs(cs[j].getRadius()));
            }
            j++;
        }

    }while(flags<8u);
//    std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
//    std::cout<<"before testing, ret.size()="<<ret.size()<<std::endl;
    for(int i=0;i<ret.size();){
        if(ret[i].testTan3(circles) == false) {
            ret.erase(ret.begin()+i);
        }else{
            i++;
        }
    }
//    std::cout<<"after testing, ret.size()="<<ret.size()<<std::endl;
    return ret;
}
void RS_ActionSnapIntersectionManual::mouseMoveEvent(QMouseEvent* e) {
    RS_DEBUG->print("RS_ActionSnapIntersectionManual::mouseMoveEvent begin");

    RS_Entity* se = catchEntity(e);
    RS_Vector mouse = graphicView->toGraph(e->x(), e->y());

    switch (getStatus()) {
    case ChooseEntity1:
        entity1 = se;
        break;

    case ChooseEntity2: {
            entity2 = se;
            coord = mouse;

            RS_VectorSolutions sol =
                RS_Information::getIntersection(entity1, entity2, false);

            //for (int i=0; i<sol.getNumber(); i++) {
            //    ip = sol.get(i);
            //    break;
            //}

            RS_Vector ip = sol.getClosest(coord);

            if (ip.valid) {
                deletePreview();
                preview->addEntity(
					new RS_Circle(preview.get(),
                                  RS_CircleData(
                                      ip,
                                      graphicView->toGraphDX(4))));
                drawPreview();

                RS_DIALOGFACTORY->updateCoordinateWidget(ip,
                        ip - graphicView->getRelativeZero());

            }
        }
        break;

    default:
        break;
    }

    RS_DEBUG->print("RS_ActionSnapIntersectionManual::mouseMoveEvent end");
}
void RS_ActionDrawCircleCR::reset() {
    data = RS_CircleData(RS_Vector(false), 0.0);
}
예제 #5
0
void RS_ActionDrawArc::mouseMoveEvent(QMouseEvent* e) {
    RS_DEBUG->print("RS_ActionDrawArc::mouseMoveEvent begin");

    RS_Vector mouse = snapPoint(e);
    switch (getStatus()) {
    case SetCenter:
        data.center = mouse;
        break;

    case SetRadius:
        if (data.center.valid) {
            data.radius = data.center.distanceTo(mouse);
            deletePreview();
            preview->addEntity(new RS_Circle(preview,
                                             RS_CircleData(data.center,
                                                           data.radius)));
            drawPreview();
        }
        break;

    case SetAngle1:
        data.angle1 = data.center.angleTo(mouse);
        if (data.reversed) {
            data.angle2 = RS_Math::correctAngle(data.angle1-M_PI/3);
        } else {
            data.angle2 = RS_Math::correctAngle(data.angle1+M_PI/3);
        }
        deletePreview();
        preview->addEntity(new RS_Arc(preview,
                                      data));
        drawPreview();
        break;

    case SetAngle2:
        data.angle2 = data.center.angleTo(mouse);
        deletePreview();
        preview->addEntity(new RS_Arc(preview,
                                      data));
        drawPreview();
        break;

    case SetIncAngle:
        data.angle2 = data.angle1 + data.center.angleTo(mouse);
        deletePreview();
        preview->addEntity(new RS_Arc(preview,
                                      data));
        drawPreview();
        break;

    case SetChordLength: {
            double x = data.center.distanceTo(mouse);
            if (fabs(x/(2*data.radius))<=1.0) {
                data.angle2 = data.angle1 + asin(x/(2*data.radius)) * 2;
                deletePreview();
                preview->addEntity(new RS_Arc(preview,
                                              data));
                drawPreview();
            }
        }
        break;

    default:
        break;

    }

    RS_DEBUG->print("RS_ActionDrawArc::mouseMoveEvent end");
}
예제 #6
0
/** solve one of the eight Appollonius Equations
| Cx - Ci|^2=(Rx+Ri)^2
with Cx the center of the common tangent circle, Rx the radius. Ci and Ri are the Center and radius of the i-th existing circle
**/
QList<RS_Circle> RS_Circle::solveAppolloniusSingle(const QList<RS_Circle>& circles)
{
//          std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
//          for(int i=0;i<circles.size();i++){
//std::cout<<"i="<<i<<"\t center="<<circles[i].getCenter()<<"\tr="<<circles[i].getRadius()<<std::endl;
//          }
    QList<RS_Circle> ret;

    QList<RS_Vector> centers;
    QList<double> radii;

    for(size_t i=0;i<3;i++){
        if(circles[i].getCenter().valid==false) return ret;
        centers.push_back(circles[i].getCenter());
        radii.push_back(fabs(circles[i].getRadius()));
    }
/** form the linear equation to solve center in radius **/
    QVector<QVector<double> > mat(2,QVector<double>(3,0.));
    mat[0][0]=centers[2].x - centers[0].x;
    mat[0][1]=centers[2].y - centers[0].y;
    mat[1][0]=centers[2].x - centers[1].x;
    mat[1][1]=centers[2].y - centers[1].y;
    if(fabs(mat[0][0]*mat[1][1] - mat[0][1]*mat[1][0])<RS_TOLERANCE*RS_TOLERANCE){
//        DEBUG_HEADER();
//        std::cout<<"The provided circles are in a line, not common tangent circle"<<std::endl;
        size_t i0=0;
        if( centers[0].distanceTo(centers[1]) <= RS_TOLERANCE ||  centers[0].distanceTo(centers[2]) <= RS_TOLERANCE) i0 = 1;
        LC_Quadratic lc0(& (circles[i0]), & (circles[(i0+1)%3]));
        LC_Quadratic lc1(& (circles[i0]), & (circles[(i0+2)%3]));
        auto&& c0 = LC_Quadratic::getIntersection(lc0, lc1);
//        qDebug()<<"c0.size()="<<c0.size();
        for(size_t i=0; i<c0.size(); i++){
            const double dc =  c0[i].distanceTo(centers[i0]);
            ret<<RS_Circle(NULL, RS_CircleData(c0[i], fabs(dc - radii[i0])));
            if( dc > radii[i0]) {
                ret<<RS_Circle(NULL, RS_CircleData(c0[i], dc + radii[i0]));
            }
        }
        return ret;
    }
    // r^0 term
    mat[0][2]=0.5*(centers[2].squared()-centers[0].squared()+radii[0]*radii[0]-radii[2]*radii[2]);
    mat[1][2]=0.5*(centers[2].squared()-centers[1].squared()+radii[1]*radii[1]-radii[2]*radii[2]);
    std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
    for(unsigned short i=0;i<=1;i++){
        std::cout<<"eqs P:"<<i<<" : "<<mat[i][0]<<"*x + "<<mat[i][1]<<"*y = "<<mat[i][2]<<std::endl;
    }
//    QVector<QVector<double> > sm(2,QVector<double>(2,0.));
    QVector<double> sm(2,0.);
    if(RS_Math::linearSolver(mat,sm)==false){
        return ret;
    }

    RS_Vector vp(sm[0],sm[1]);
//      std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
//      std::cout<<"vp="<<vp<<std::endl;

    // r term
    mat[0][2]= radii[0]-radii[2];
    mat[1][2]= radii[1]-radii[2];
//    for(unsigned short i=0;i<=1;i++){
//        std::cout<<"eqs Q:"<<i<<" : "<<mat[i][0]<<"*x + "<<mat[i][1]<<"*y = "<<mat[i][2]<<std::endl;
//    }
    if(RS_Math::linearSolver(mat,sm)==false){
        return ret;
    }
    RS_Vector vq(sm[0],sm[1]);
//      std::cout<<"vq="<<vq<<std::endl;
    //form quadratic equation for r
    RS_Vector dcp=vp-centers[0];
    double a=vq.squared()-1.;
    if(fabs(a)<RS_TOLERANCE*1e-4) {
        return ret;
    }
    std::vector<double> ce(0,0.);
    ce.push_back(2.*(dcp.dotP(vq)-radii[0])/a);
    ce.push_back((dcp.squared()-radii[0]*radii[0])/a);
    std::vector<double>&& vr=RS_Math::quadraticSolver(ce);
    for(size_t i=0; i < vr.size();i++){
        if(vr.at(i)<RS_TOLERANCE) continue;
        ret<<RS_Circle(NULL,RS_CircleData(vp+vq*vr.at(i),vr.at(i)));
    }
//    std::cout<<__FILE__<<" : "<<__FUNCTION__<<" : line "<<__LINE__<<std::endl;
//    std::cout<<"Found "<<ret.size()<<" solutions"<<std::endl;

    return ret;
}
예제 #7
0
/**
 * We could properly speed this up by calling the draw function of this snapper within the paint event
 * this will avoid creating/deletion of the lines
 */
void RS_Snapper::drawSnapper() {
        graphicView->getOverlayContainer(RS2::Snapper)->clear();
    if (!finished && snapSpot.valid) {
                RS_EntityContainer *container=graphicView->getOverlayContainer(RS2::Snapper);
                RS_Pen crossHairPen(RS_Color(255,194,0), RS2::Width00, RS2::DashLine2);

        if (snapCoord.valid) {
                        RS_DEBUG->print("RS_Snapper::Snapped draw start");
                        // Pen for snapper
                        RS_Pen pen(RS_Color(255,194,0), RS2::Width00, RS2::SolidLine);
                        pen.setScreenWidth(1);

                        // Circle to show snap area
                        RS_Circle *circle=new RS_Circle(NULL, RS_CircleData(snapCoord, 4/graphicView->getFactor().x));
                        circle->setPen(pen);

                        container->addEntity(circle);

                        // crosshairs:
                        if (showCrosshairs==true) {
                            if(graphicView->isGridIsometric()) {//isometric crosshair
                                RS2::CrosshairType chType=graphicView->getCrosshairType();
                                RS_Vector direction1;
                                RS_Vector direction2(0.,1.);
                                double l=graphicView->getWidth()+graphicView->getHeight();
                                switch(chType){
                                case RS2::RightCrosshair:
                                    direction1=RS_Vector(M_PI*5./6.)*l;
                                    direction2*=l;
                                    break;
                                case RS2::LeftCrosshair:
                                    direction1=RS_Vector(M_PI*1./6.)*l;
                                    direction2*=l;
                                    break;
                                default:
                                    direction1=RS_Vector(M_PI*1./6.)*l;
                                    direction2=RS_Vector(M_PI*5./6.)*l;
                                }
                                RS_Vector center(graphicView->toGui(snapCoord));
                                RS_OverlayLine *line=new RS_OverlayLine(NULL,RS_LineData(center-direction1,center+direction1));
                                line->setPen(crossHairPen);
                                container->addEntity(line);
                                line=new RS_OverlayLine(NULL,RS_LineData(center-direction2,center+direction2));
                                line->setPen(crossHairPen);
                                container->addEntity(line);
                            }else{//orthogonal crosshair


                                RS_OverlayLine *line=new RS_OverlayLine(NULL, RS_LineData(RS_Vector(0, graphicView->toGuiY(snapCoord.y)),
                                                                                          RS_Vector(graphicView->getWidth(), graphicView->toGuiY(snapCoord.y))));
                                line->setPen(crossHairPen);
                                container->addEntity(line);

                                line=new RS_OverlayLine(NULL, RS_LineData(RS_Vector(graphicView->toGuiX(snapCoord.x),0),
                                                                          RS_Vector(graphicView->toGuiX(snapCoord.x), graphicView->getHeight())));
                                line->setPen(crossHairPen);
                                container->addEntity(line);
                            }

                        }
                        graphicView->redraw(RS2::RedrawOverlay); // redraw will happen in the mouse movement event
                        RS_DEBUG->print("RS_Snapper::Snapped draw end");
        }
        if (snapCoord.valid && snapCoord!=snapSpot) {

                        RS_OverlayLine *line=new RS_OverlayLine(NULL, RS_LineData(graphicView->toGui(snapSpot)+RS_Vector(-5,0),
                                                                                                                                          graphicView->toGui(snapSpot)+RS_Vector(-1,4)));
                        line->setPen(crossHairPen);
                        container->addEntity(line);
                        line=new RS_OverlayLine(NULL, RS_LineData(graphicView->toGui(snapSpot)+RS_Vector(0,5),
                                                                                                                                          graphicView->toGui(snapSpot)+RS_Vector(4,1)));
                        line->setPen(crossHairPen);
                        container->addEntity(line);
                        line=new RS_OverlayLine(NULL, RS_LineData(graphicView->toGui(snapSpot)+RS_Vector(5,0),
                                                                                                                                          graphicView->toGui(snapSpot)+RS_Vector(1,-4)));
                        line->setPen(crossHairPen);
                        container->addEntity(line);
                        line=new RS_OverlayLine(NULL, RS_LineData(graphicView->toGui(snapSpot)+RS_Vector(0,-5),
                                                                                                                                          graphicView->toGui(snapSpot)+RS_Vector(-4,-1)));
                        line->setPen(crossHairPen);
                        container->addEntity(line);

                        graphicView->redraw(RS2::RedrawOverlay); // redraw will happen in the mouse movement event
        }
    }

}
예제 #8
0
/*RS_EntityContainer* parent,
                 const RS_LineData& d*/
Plugin_Entity::Plugin_Entity(RS_EntityContainer* parent, enum DPI::ETYPE type){
    hasContainer = false;
    entity = NULL;
    switch (type) {
    case DPI::POINT:
        entity = new RS_Point(parent, RS_PointData(RS_Vector(0,0)));
        break;
    case DPI::LINE:
        entity = new RS_Line(parent, RS_LineData());
        break;
/*    case DPI::CONSTRUCTIONLINE:
        entity = new RS_ConstructionLine();
        break;*/
    case DPI::CIRCLE:
        entity = new RS_Circle(parent, RS_CircleData());
        break;
    case DPI::ARC:
        entity = new RS_Arc(parent, RS_ArcData());
        break;
    case DPI::ELLIPSE:
        entity = new RS_Ellipse(parent, RS_EllipseData(RS_Vector(0,0), RS_Vector(0,0),0.0,0.0,0.0,false));
        break;
    case DPI::IMAGE:
        entity = new RS_Image(parent, RS_ImageData());
        break;
/*    case DPI::OVERLAYBOX:
        entity = new RS_OverlayBox();
        break;
    case DPI::SOLID:
        entity = new RS_Solid();
        break;*/
    case DPI::TEXT:
        entity = new RS_Text(parent, RS_TextData());
        break;
/*    case DPI::INSERT:
        entity = new RS_Insert();
        break;*/
    case DPI::POLYLINE:
        entity = new RS_Polyline(parent, RS_PolylineData());
        break;
/*    case DPI::SPLINE:
        entity = new RS_Spline();
        break;
    case DPI::HATCH:
        entity = new RS_Hatch();
        break;
    case DPI::DIMLEADER:
        entity = new RS_Leader();
        break;
    case DPI::DIMALIGNED:
        entity = new RS_DimAligned();
        break;
    case DPI::DIMLINEAR:
        entity = new RS_DimLinear();
        break;
    case DPI::DIMRADIAL:
        entity = new RS_DimRadial();
        break;
    case DPI::DIMDIAMETRIC:
        entity = new RS_DimDiametric();
        break;
    case DPI::DIMANGULAR:
        entity = new RS_DimAngular();
        break;*/
    default:
        break;
    }
}
예제 #9
0
    /**
     * Creates a tangent between a given point and a circle or arc.
     * Out of the 2 possible tangents, the one closest to
     * the given coordinate is returned.
     *
     * @param coord Coordinate to define which tangent we want (typically a
     *              mouse coordinate).
     * @param point Point.
     * @param circle Circle, arc or ellipse entity.
     */
    RS_Line* RS_Creation::createTangent1(const RS_Vector& coord,
                                         const RS_Vector& point,
                                         RS_Entity* circle) {
        RS_Line* ret = NULL;
        RS_Vector circleCenter;

        // check given entities:
        if (circle==NULL || !point.valid ||
                (circle->rtti()!=RS2::EntityArc && circle->rtti()!=RS2::EntityCircle
                 && circle->rtti()!=RS2::EntityEllipse)) {

            return NULL;
        }

        if (circle->rtti()==RS2::EntityCircle) {
            circleCenter = ((RS_Circle*)circle)->getCenter();
        } else if (circle->rtti()==RS2::EntityArc) {
            circleCenter = ((RS_Arc*)circle)->getCenter();
        } else if (circle->rtti()==RS2::EntityEllipse) {
            circleCenter = ((RS_Ellipse*)circle)->getCenter();
        }

        // the two tangent points:
        RS_VectorSolutions sol;

        // calculate tangent points for arcs / circles:
        if (circle->rtti()!=RS2::EntityEllipse) {
            // create temp. thales circle:
            RS_Vector tCenter = (point + circleCenter)/2.0;
            double tRadius = point.distanceTo(tCenter);

            RS_Circle tmp(NULL, RS_CircleData(tCenter, tRadius));

            // get the two intersection points which are the tangent points:
            sol = RS_Information::getIntersection(&tmp, circle, false);
        }

        // calculate tangent points for ellipses:
        else {
            RS_Ellipse* el = (RS_Ellipse*)circle;
            //sol.alloc(2);
            //sol.set(0, circleCenter);
            //sol.set(1, circleCenter);


            double a = el->getMajorRadius();     // the length of the major axis / 2
            double b = el->getMinorRadius();     // the length of the minor axis / 2

            // rotate and move point:
            RS_Vector point2 = point;
            point2.move(-el->getCenter());
            point2.rotate(-el->getAngle());

            double xp = point2.x;             // coordinates of the given point
            double yp = point2.y;

            double xt1;                      // Tangent point 1
            double yt1;
            double xt2;                      // Tangent point 2
            double yt2;

            double a2 = a * a;
            double b2 = b * b;
            double d = a2 / b2 * yp / xp;
            double e = a2 / xp;
            double af = b2 * d * d + a2;
            double bf = -b2 * d * e * 2.0;
            double cf = b2 * e * e - a2 * b2;
            double t = sqrt(bf * bf - af * cf * 4.0);
            yt1 = (t - bf) / (af * 2.0);
            xt1 = e - d * yt1;
            yt2 = (-t - bf) / (af * 2.0);
            xt2 = e - d * yt2;

            RS_Vector s1 = RS_Vector(xt1, yt1);
            RS_Vector s2 = RS_Vector(xt2, yt2);

            s1.rotate(el->getAngle());
            s1.move(el->getCenter());

            s2.rotate(el->getAngle());
            s2.move(el->getCenter());

            sol.push_back(s1);
            sol.push_back(s2);


        }

        if (sol.getNumber() < 2 ) {
                return NULL;
        }
        if (!sol.get(0).valid || !sol.get(1).valid) {
            return NULL;
        }

        // create all possible tangents:
        RS_Line* poss[2];

        RS_LineData d;

        d = RS_LineData(sol.get(0), point);
        poss[0] = new RS_Line(NULL, d);
        d = RS_LineData(sol.get(1), point);
        poss[1] = new RS_Line(NULL, d);

        // find closest tangent:
        double minDist = RS_MAXDOUBLE;
        double dist;
        int idx = -1;
        for (int i=0; i<2; ++i) {
            dist = poss[i]->getDistanceToPoint(coord);
            if (dist<minDist) {
                minDist = dist;
                idx = i;
            }
        }

        // create the closest tangent:
        if (idx!=-1) {
            RS_LineData d = poss[idx]->getData();

            for (int i=0; i<2; ++i) {
                delete poss[i];
            }

            if (document!=NULL && handleUndo) {
                document->startUndoCycle();
            }

            ret = new RS_Line(container, d);
            ret->setLayerToActive();
            ret->setPenToActive();
            if (container!=NULL) {
                container->addEntity(ret);
            }
            if (document!=NULL && handleUndo) {
                document->addUndoable(ret);
                document->endUndoCycle();
            }
            if (graphicView!=NULL) {
                graphicView->drawEntity(ret);
            }
        } else {
            ret = NULL;
        }

        return ret;
    }