コード例 #1
0
ファイル: rs_graphic.cpp プロジェクト: janelia-idf/LibreCAD
/**
 * @return The insertion point of the drawing into the paper space.
 * This is the distance from the lower left paper edge to the zero
 * point of the drawing. DXF: $PINSBASE.
 */
RS_Vector RS_Graphic::getPaperInsertionBase() {
    return getVariableVector("$PINSBASE", RS_Vector(0.0,0.0));
}
コード例 #2
0
void RS_Painter::drawRect(const RS_Vector& p1, const RS_Vector& p2) {
	drawLine(RS_Vector(p1.x, p1.y), RS_Vector(p2.x, p1.y));
    drawLine(RS_Vector(p2.x, p1.y), RS_Vector(p2.x, p2.y));
    drawLine(RS_Vector(p2.x, p2.y), RS_Vector(p1.x, p2.y));
    drawLine(RS_Vector(p1.x, p2.y), RS_Vector(p1.x, p1.y));
}
コード例 #3
0
ファイル: rs_vector.cpp プロジェクト: Cantar4/LibreCAD
/**
 * Constructor for num solutions.
 */
RS_VectorSolutions::RS_VectorSolutions(int num):
	vector(num, RS_Vector(false))
  ,tangent(false)
{
}
コード例 #4
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());
        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;
    }
}
コード例 #5
0
void Plugin_Entity::rotate(QPointF center, double angle){
    entity->rotate( RS_Vector(center.x(), center.y()) , angle);
}
コード例 #6
0
ファイル: rs_polyline.cpp プロジェクト: Cantar4/LibreCAD
void RS_Polyline::rotate(const RS_Vector& center, const double& angle) {
    rotate(center, RS_Vector(angle));
}
コード例 #7
0
RS_Vector RS_Circle::getNearestDist(double /*distance*/,
                                  bool /*startp*/) {

    return RS_Vector(false);
}
コード例 #8
0
void LC_ActionDrawCircle2PR::reset() {
	data->reset();
	data->radius=0.;
    point1 = RS_Vector(false);
    point2 = RS_Vector(false);
}
コード例 #9
0
void RS_ActionPolylineAdd::init(int status) {
	RS_ActionInterface::init(status);
	addEntity = addSegment = NULL;
	addCoord = RS_Vector(false);
}
コード例 #10
0
ファイル: rs_actiondrawcircle2p.cpp プロジェクト: Akaur/qdraw
void RS_ActionDrawCircle2P::reset() {
    data.reset();
    point1 = RS_Vector(false);
    point2 = RS_Vector(false);
}
コード例 #11
0
ファイル: rs_hatch.cpp プロジェクト: Joeycc/LibreCAD
/**
 * Updates the Hatch. Called when the
 * hatch or it's data, position, alignment, .. changes.
 */
void RS_Hatch::update() {
        RS_DEBUG->print("RS_Hatch::update");
        RS_DEBUG->print("RS_Hatch::update: contour has %d loops", count());

    updateError = HATCH_OK;
    if (updateRunning) {
        return;
    }

    if (updateEnabled==false) {
        return;
    }

    if (data.solid==true) {
        calculateBorders();
        return;
    }

    RS_DEBUG->print("RS_Hatch::update");
    updateRunning = true;

    // delete old hatch:
    if (hatch) {
        removeEntity(hatch);
		hatch = nullptr;
    }

    if (isUndone()) {
        updateRunning = false;
        return;
    }

    if (!validate()) {
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Hatch::update: invalid contour in hatch found");
        updateRunning = false;
        updateError = HATCH_INVALID_CONTOUR;
        return;
    }

    // search pattern:
    RS_DEBUG->print("RS_Hatch::update: requesting pattern");
    RS_Pattern* pat = RS_PATTERNLIST->requestPattern(data.pattern);
	if (!pat) {
        updateRunning = false;
        RS_DEBUG->print("RS_Hatch::update: requesting pattern: not found");
        updateError = HATCH_PATTERN_NOT_FOUND;
        return;
    }
    RS_DEBUG->print("RS_Hatch::update: requesting pattern: OK");

    RS_DEBUG->print("RS_Hatch::update: cloning pattern");
    pat = (RS_Pattern*)pat->clone();
    RS_DEBUG->print("RS_Hatch::update: cloning pattern: OK");

    // scale pattern
    RS_DEBUG->print("RS_Hatch::update: scaling pattern");
    pat->scale(RS_Vector(0.0,0.0), RS_Vector(data.scale, data.scale));
    pat->calculateBorders();
    forcedCalculateBorders();
    RS_DEBUG->print("RS_Hatch::update: scaling pattern: OK");

    // find out how many pattern-instances we need in x/y:
    int px1, py1, px2, py2;
    double f;
    RS_Hatch* copy = (RS_Hatch*)this->clone();
    copy->rotate(RS_Vector(0.0,0.0), -data.angle);
    copy->forcedCalculateBorders();

    // create a pattern over the whole contour.
    RS_Vector pSize = pat->getSize();
    RS_Vector rot_center=pat->getMin();
//    RS_Vector cPos = getMin();
    RS_Vector cSize = getSize();


    RS_DEBUG->print("RS_Hatch::update: pattern size: %f/%f", pSize.x, pSize.y);
    RS_DEBUG->print("RS_Hatch::update: contour size: %f/%f", cSize.x, cSize.y);

    if (cSize.x<1.0e-6 || cSize.y<1.0e-6 ||
            pSize.x<1.0e-6 || pSize.y<1.0e-6 ||
            cSize.x>RS_MAXDOUBLE-1 || cSize.y>RS_MAXDOUBLE-1 ||
            pSize.x>RS_MAXDOUBLE-1 || pSize.y>RS_MAXDOUBLE-1) {
        delete pat;
        delete copy;
        updateRunning = false;
        RS_DEBUG->print("RS_Hatch::update: contour size or pattern size too small");
        updateError = HATCH_TOO_SMALL;
        return;
    }

    // avoid huge memory consumption:
    else if ( cSize.x* cSize.y/(pSize.x*pSize.y)>1e4) {
        RS_DEBUG->print("RS_Hatch::update: contour size too large or pattern size too small");
        delete pat;
        delete copy;
        updateError = HATCH_AREA_TOO_BIG;
        return;
    }

    f = copy->getMin().x/pSize.x;
    px1 = (int)floor(f);
    f = copy->getMin().y/pSize.y;
    py1 = (int)floor(f);
    f = copy->getMax().x/pSize.x;
    px2 = (int)ceil(f);
    f = copy->getMax().y/pSize.y;
    py2 = (int)ceil(f);
    RS_Vector dvx=RS_Vector(data.angle)*pSize.x;
    RS_Vector dvy=RS_Vector(data.angle+M_PI*0.5)*pSize.y;
    pat->rotate(rot_center, data.angle);
    pat->move(-rot_center);


    RS_EntityContainer tmp;   // container for untrimmed lines

    // adding array of patterns to tmp:
    RS_DEBUG->print("RS_Hatch::update: creating pattern carpet");

    for (int px=px1; px<px2; px++) {
		for (int py=py1; py<py2; py++) {
			for(auto e: *pat){
                RS_Entity* te=e->clone();
                te->move(dvx*px + dvy*py);
                tmp.addEntity(te);
            }
        }
    }

    delete pat;
    pat = nullptr;
    delete copy;
    copy = nullptr;
    RS_DEBUG->print("RS_Hatch::update: creating pattern carpet: OK");


    RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet");
    // cut pattern to contour shape:
    RS_EntityContainer tmp2;   // container for small cut lines
	RS_Line* line = nullptr;
	RS_Arc* arc = nullptr;
	RS_Circle* circle = nullptr;
	RS_Ellipse* ellipse = nullptr;
	for(auto e: tmp){

		line = nullptr;
		arc = nullptr;
		circle = nullptr;
		ellipse = nullptr;

        RS_Vector startPoint;
        RS_Vector endPoint;
        RS_Vector center = RS_Vector(false);
        bool reversed=false;

        switch(e->rtti()){
        case RS2::EntityLine:
            line=static_cast<RS_Line*>(e);
            startPoint = line->getStartpoint();
            endPoint = line->getEndpoint();
            break;
        case RS2::EntityArc:
            arc=static_cast<RS_Arc*>(e);
            startPoint = arc->getStartpoint();
            endPoint = arc->getEndpoint();
            center = arc->getCenter();
            reversed = arc->isReversed();
            break;
        case RS2::EntityCircle:
            circle=static_cast<RS_Circle*>(e);
            startPoint = circle->getCenter()
                    + RS_Vector(circle->getRadius(), 0.0);
            endPoint = startPoint;
            center = circle->getCenter();
            break;
        case RS2::EntityEllipse:
            ellipse = static_cast<RS_Ellipse*>(e);
            startPoint = ellipse->getStartpoint();
            endPoint = ellipse->getEndpoint();
            center = ellipse->getCenter();
            reversed = ellipse->isReversed();
            break;
        default:
            continue;
        }

        // getting all intersections of this pattern line with the contour:
        QList<std::shared_ptr<RS_Vector> > is;

		for(auto loop: entities){

            if (loop->isContainer()) {
				for(auto p: * static_cast<RS_EntityContainer*>(loop)){

                    RS_VectorSolutions sol =
                        RS_Information::getIntersection(e, p, true);

					for (const RS_Vector& vp: sol){
						if (vp.valid) {
							is.append(std::shared_ptr<RS_Vector>(
										  new RS_Vector(vp)
										  ));
							RS_DEBUG->print("  pattern line intersection: %f/%f",
											vp.x, vp.y);
						}
					}
				}
			}
		}


        QList<std::shared_ptr<RS_Vector> > is2;//to be filled with sorted intersections
        is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(startPoint)));

        // sort the intersection points into is2 (only if there are intersections):
        if(is.size() == 1)
        {//only one intersection
            is2.append(is.first());
        }
        else if(is.size() > 1)
        {
            RS_Vector sp = startPoint;
            double sa = center.angleTo(sp);
			if(ellipse ) sa=ellipse->getEllipseAngle(sp);
            bool done;
            double minDist;
            double dist = 0.0;
            std::shared_ptr<RS_Vector> av;
            std::shared_ptr<RS_Vector> v;
            RS_Vector last = RS_Vector(false);
            do {
                done = true;
                minDist = RS_MAXDOUBLE;
                av.reset();
                for (int i = 0; i < is.size(); ++i) {
                    v = is.at(i);
                    double a;
                    switch(e->rtti()){
                    case RS2::EntityLine:
                        dist = sp.distanceTo(*v);
                        break;
                    case RS2::EntityArc:
                    case RS2::EntityCircle:
                        a = center.angleTo(*v);
                        dist = reversed?
                                    fmod(sa - a + 2.*M_PI,2.*M_PI):
                                    fmod(a - sa + 2.*M_PI,2.*M_PI);
                        break;
                    case RS2::EntityEllipse:
                        a = ellipse->getEllipseAngle(*v);
                        dist = reversed?
                                    fmod(sa - a + 2.*M_PI,2.*M_PI):
                                    fmod(a - sa + 2.*M_PI,2.*M_PI);
                        break;
                    default:
                        break;

                    }

                    if (dist<minDist) {
                        minDist = dist;
                        done = false;
                        av = v;
                    }
                }

                // copy to sorted list, removing double points
                if (!done && av.get()) {
                    if (last.valid==false || last.distanceTo(*av)>RS_TOLERANCE) {
                        is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(*av)));
                        last = *av;
                    }
#if QT_VERSION < 0x040400
                    emu_qt44_removeOne(is, av);
#else
                    is.removeOne(av);
#endif

                    av.reset();
                }
            } while(!done);
        }

is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(endPoint)));

        // add small cut lines / arcs to tmp2:
            for (int i = 1; i < is2.size(); ++i) {
                auto v1 = is2.at(i-1);
                auto v2 = is2.at(i);


                if (line) {

					tmp2.addEntity(new RS_Line{&tmp2, *v1, *v2});
                } else if (arc || circle) {
                    if(fabs(center.angleTo(*v2)-center.angleTo(*v1)) > RS_TOLERANCE_ANGLE)
                    {//don't create an arc with a too small angle
                        tmp2.addEntity(new RS_Arc(&tmp2,
                                                  RS_ArcData(center,
                                                             center.distanceTo(*v1),
                                                             center.angleTo(*v1),
                                                             center.angleTo(*v2),
                                                             reversed)));
                    }

                }
            }

    }

    // updating hatch / adding entities that are inside
    RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet: OK");

    //RS_EntityContainer* rubbish = new RS_EntityContainer(getGraphic());

    // the hatch pattern entities:
    hatch = new RS_EntityContainer(this);
    hatch->setPen(RS_Pen(RS2::FlagInvalid));
	hatch->setLayer(nullptr);
    hatch->setFlag(RS2::FlagTemp);

    //calculateBorders();

	for(auto e: tmp2){

        RS_Vector middlePoint;
        RS_Vector middlePoint2;
        if (e->rtti()==RS2::EntityLine) {
			RS_Line* line = static_cast<RS_Line*>(e);
            middlePoint = line->getMiddlePoint();
            middlePoint2 = line->getNearestDist(line->getLength()/2.1,
                                                line->getStartpoint());
        } else if (e->rtti()==RS2::EntityArc) {
			RS_Arc* arc = static_cast<RS_Arc*>(e);
            middlePoint = arc->getMiddlePoint();
            middlePoint2 = arc->getNearestDist(arc->getLength()/2.1,
                                               arc->getStartpoint());
        } else {
			middlePoint = RS_Vector{false};
			middlePoint2 = RS_Vector{false};
        }

        if (middlePoint.valid) {
            bool onContour=false;

            if (RS_Information::isPointInsideContour(
                        middlePoint,
                        this, &onContour) ||
                    RS_Information::isPointInsideContour(middlePoint2, this)) {

                RS_Entity* te = e->clone();
				te->setPen(RS2::FlagInvalid);
				te->setLayer(nullptr);
                te->reparent(hatch);
                hatch->addEntity(te);
            }
        }
    }

    addEntity(hatch);
    //getGraphic()->addEntity(rubbish);

    forcedCalculateBorders();

    // deactivate contour:
    activateContour(false);

    updateRunning = false;

    RS_DEBUG->print("RS_Hatch::update: OK");
}
コード例 #12
0
void QG_CoordinateWidget::setGraphic(RS_Graphic* graphic) {
    this->graphic = graphic;

    setCoordinates(RS_Vector(0.0,0.0), RS_Vector(0.0,0.0), true);
}
コード例 #13
0
ファイル: qg_graphicview.cpp プロジェクト: mcanthony/LibreCAD
/**
 * Called whenever the graphic view has changed.
 * Adjusts the scrollbar ranges / steps.
 */
void QG_GraphicView::adjustOffsetControls() {
        static bool running = false;

        if (running) {
                return;
        }

        running = true;

    RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() begin");

    if (container==NULL || hScrollBar==NULL || vScrollBar==NULL) {
        return;
    }

    int ox = getOffsetX();
    int oy = getOffsetY();

    RS_Vector min = container->getMin();
    RS_Vector max = container->getMax();

    // no drawing yet - still allow to scroll
    if (max.x < min.x+1.0e-6 ||
            max.y < min.y+1.0e-6 ||
                max.x > RS_MAXDOUBLE ||
                max.x < RS_MINDOUBLE ||
                min.x > RS_MAXDOUBLE ||
                min.x < RS_MINDOUBLE ||
                max.y > RS_MAXDOUBLE ||
                max.y < RS_MINDOUBLE ||
                min.y > RS_MAXDOUBLE ||
                min.y < RS_MINDOUBLE ) {
        min = RS_Vector(-10,-10);
        max = RS_Vector(100,100);
	}


	int minVal = (int)(-ox-getWidth()*0.5
					   - QG_SCROLLMARGIN - getBorderLeft());
	int maxVal = (int)(-ox+getWidth()*0.5
					   + QG_SCROLLMARGIN + getBorderRight());

	if (minVal<=maxVal) {
		hScrollBar->setRange(minVal, maxVal);
	}

	minVal = (int)(oy-getHeight()*0.5
				   - QG_SCROLLMARGIN - getBorderTop());
	maxVal = (int)(oy+getHeight()*0.5
				   +QG_SCROLLMARGIN + getBorderBottom());

	if (minVal<=maxVal) {
		vScrollBar->setRange(minVal, maxVal);
	}

	hScrollBar->setPageStep(getWidth());
	vScrollBar->setPageStep(getHeight());

	hScrollBar->setValue(-ox);
	vScrollBar->setValue(oy);


    slotHScrolled(-ox);
    slotVScrolled(oy);


    RS_DEBUG->print("H min: %d / max: %d / step: %d / value: %d\n",
                    hScrollBar->minimum(), hScrollBar->maximum(),
                    hScrollBar->pageStep(), ox);
//    DEBUG_HEADER
    RS_DEBUG->print(/*RS_Debug::D_WARNING, */"V min: %d / max: %d / step: %d / value: %d\n",
                    vScrollBar->minimum(), vScrollBar->maximum(),
                    vScrollBar->pageStep(), oy);

    RS_DEBUG->print("QG_GraphicView::adjustOffsetControls() end");

        running = false;
}
コード例 #14
0
ファイル: qg_graphicview.cpp プロジェクト: mcanthony/LibreCAD
/**
 * mouse wheel event. zooms in/out or scrolls when
 * shift or ctrl is pressed.
 */
void QG_GraphicView::wheelEvent(QWheelEvent *e) {
    //RS_DEBUG->print("wheel: %d", e->delta());

    //printf("state: %d\n", e->state());
    //printf("ctrl: %d\n", Qt::ControlButton);

    if (container==NULL) {
        return;
    }

    RS_Vector mouse = toGraph(RS_Vector(e->x(), e->y()));

#if QT_VERSION >= 0x050200
    QPoint numPixels = e->pixelDelta();

    // high-resolution scrolling triggers Pan instead of Zoom logic
    isSmoothScrolling |= !numPixels.isNull();

    if (isSmoothScrolling) {
        if (e->phase() == Qt::ScrollEnd) isSmoothScrolling = false;

        if (!numPixels.isNull()) {
            if (e->modifiers()==Qt::ControlModifier) {
                // Hold ctrl to zoom. 1 % per pixel
                double v = -numPixels.y() / 100.;
                RS2::ZoomDirection direction;
                double factor;

                if (v < 0) {
                    direction = RS2::Out; factor = 1-v;
                } else {
                    direction = RS2::In;  factor = 1+v;
                }

                setCurrentAction(new RS_ActionZoomIn(*container, *this, direction,
                                                     RS2::Both, mouse, factor));
            } else {
                // otherwise, scroll
				//scroll by scrollbars: issue #479
				hScrollBar->setValue(hScrollBar->value() - numPixels.x());
				vScrollBar->setValue(vScrollBar->value() - numPixels.y());

//                setCurrentAction(new RS_ActionZoomScroll(numPixels.x(), numPixels.y(),
//                                                         *container, *this));
            }
            redraw();
        }
        e->accept();
        return;
    }
#endif

    if (e->delta() == 0) {
        // A zero delta event occurs when smooth scrolling is ended. Ignore this
        e->accept();
        return;
    }

    bool scroll = false;
    RS2::Direction direction = RS2::Up;

    // scroll up / down:
    if (e->modifiers()==Qt::ControlModifier) {
        scroll = true;
        switch(e->orientation()){
        case Qt::Horizontal:
            direction=(e->delta()>0)?RS2::Left:RS2::Right;
            break;
        default:
        case Qt::Vertical:
            direction=(e->delta()>0)?RS2::Up:RS2::Down;
        }
    }

    // scroll left / right:
    else if	(e->modifiers()==Qt::ShiftModifier) {
        scroll = true;
        switch(e->orientation()){
        case Qt::Horizontal:
            direction=(e->delta()>0)?RS2::Up:RS2::Down;
            break;
        default:
        case Qt::Vertical:
            direction=(e->delta()>0)?RS2::Left:RS2::Right;
        }
    }

    if (scroll) {
		//scroll by scrollbars: issue #479
		switch(direction){
		case RS2::Left:
		case RS2::Right:
			hScrollBar->setValue(hScrollBar->value()+e->delta());
			break;
		default:
			vScrollBar->setValue(vScrollBar->value()+e->delta());
		}

//        setCurrentAction(new RS_ActionZoomScroll(direction,
//                         *container, *this));
    }

    // zoom in / out:
    else if (e->modifiers()==0) {
        if (e->delta()>0) {
            setCurrentAction(new RS_ActionZoomIn(*container, *this,
                                                 RS2::In, RS2::Both,
                                                                                                 mouse));
        } else {
            setCurrentAction(new RS_ActionZoomIn(*container, *this,
                                                 RS2::Out, RS2::Both,
                                                                                                 mouse));
        }
    }

        redraw();

    e->accept();
}
コード例 #15
0
ファイル: rs_mtext.cpp プロジェクト: dinkel/LibreCAD
/**
 * Updates the Inserts (letters) of this text. Called when the
 * text or it's data, position, alignment, .. changes.
 * This method also updates the usedTextWidth / usedTextHeight property.
 */
void RS_MText::update() {

    RS_DEBUG->print("RS_Text::update");

    clear();

    if (isUndone()) {
        return;
    }

    usedTextWidth = 0.0;
    usedTextHeight = 0.0;

    RS_Font* font = RS_FONTLIST->requestFont(data.style);

    if (font==NULL) {
        return;
    }

    RS_Vector letterPos = RS_Vector(0.0, -9.0);
    RS_Vector letterSpace = RS_Vector(font->getLetterSpacing(), 0.0);
    RS_Vector space = RS_Vector(font->getWordSpacing(), 0.0);
    int lineCounter = 0;

    // Every single text line gets stored in this entity container
    //  so we can move the whole line around easely:
    RS_EntityContainer* oneLine = new RS_EntityContainer(this);

    // First every text line is created with
    //   alignement: top left
    //   angle: 0
    //   height: 9.0
    // Rotation, scaling and centering is done later

    // For every letter:
    for (int i=0; i<(int)data.text.length(); ++i) {
        bool handled = false;
        switch (data.text.at(i).unicode()) {
        case 0x0A:
            // line feed:
            updateAddLine(oneLine, lineCounter++);
            oneLine = new RS_EntityContainer(this);
            letterPos = RS_Vector(0.0, -9.0);
            handled = true;
            break;

        case 0x20:
            // Space:
            letterPos+=space;
            handled = true;
            break;

        case 0x5C: {
                // code (e.g. \S, \P, ..)
                i++;
                int ch = data.text.at(i).unicode();
                switch (ch) {
                case 'P':
                    updateAddLine(oneLine, lineCounter++);
                    oneLine = new RS_EntityContainer(this);
                    letterPos = RS_Vector(0.0, -9.0);
                    handled = true;
                    break;
                    case 'f':
                    case 'F':
                    //font change
                    // \f{symbol} changes font to symbol
                    // \f{} sets font to standard
                {
                    i++;
                    if(data.text.at(i).unicode()!='{') {
                        i--;
                        continue;
                    }
                    int j=data.text.indexOf('}',i);
                    if(j>i){
                        //
                        QString fontName;
                        if(j==i+1)
                            fontName="standard";
                        else
                            fontName=data.text.mid(i+1,j-i-1);
                        RS_Font* fontNew = RS_FONTLIST->requestFont(
                                    fontName
                                    );
                        if(fontNew != NULL) {
                            font=fontNew;
                        }
                        if(font==NULL) font = RS_FONTLIST->requestFont("standard");
                        i=j;
                    }
                }
                        continue;

                case 'S': {
                        QString up;
                        QString dw;
                        //letterPos += letterSpace;

                        // get upper string:
                        i++;
                        while (data.text.at(i).unicode()!='^' &&
                                                       //data.text.at(i).unicode()!='/' &&
                                                       data.text.at(i).unicode()!='\\' &&
                                                       //data.text.at(i).unicode()!='#' &&
                                i<(int)data.text.length()) {
                            up += data.text.at(i);
                            i++;
                        }

                        i++;

                                                if (data.text.at(i-1).unicode()=='^' &&
                                                     data.text.at(i).unicode()==' ') {
                                                        i++;
                                                }

                        // get lower string:
                        while (data.text.at(i).unicode()!=';' &&
                                i<(int)data.text.length()) {
                            dw += data.text.at(i);
                            i++;
                        }

                        // add texts:
                        RS_MText* upper =
                            new RS_MText(
                                oneLine,
                                RS_MTextData(letterPos + RS_Vector(0.0,9.0),
                                            4.0, 100.0, RS_MTextData::VATop, RS_MTextData::HALeft,
                                            RS_MTextData::LeftToRight, RS_MTextData::Exact,
                                            1.0, up, data.style,
                                            0.0, RS2::Update));
                                            upper->setLayer(NULL);
                        upper->setPen(RS_Pen(RS2::FlagInvalid));
                        oneLine->addEntity(upper);

                        RS_MText* lower =
                            new RS_MText(
                                oneLine,
                                RS_MTextData(letterPos+RS_Vector(0.0,4.0),
                                            4.0, 100.0, RS_MTextData::VATop, RS_MTextData::HALeft,
                                            RS_MTextData::LeftToRight, RS_MTextData::Exact,
                                            1.0, dw, data.style,
                                            0.0, RS2::Update));
                                            lower->setLayer(NULL);
                        lower->setPen(RS_Pen(RS2::FlagInvalid));
                        oneLine->addEntity(lower);

                        // move cursor:
                        upper->calculateBorders();
                        lower->calculateBorders();

                        double w1 = upper->getSize().x;
                        double w2 = lower->getSize().x;

                        if (w1>w2) {
                            letterPos += RS_Vector(w1, 0.0);
                        } else {
                            letterPos += RS_Vector(w2, 0.0);
                        }
                        letterPos += letterSpace;
                    }
                    handled = true;
                    break;

                default:
                    i--;
                    break;
                }
            }
            //if char is not handled continue in default: statement
            if (handled)
                break;

        default: {
                // One Letter:
                QString letterText = QString(data.text.at(i));
                if (font->findLetter(letterText) == NULL) {
                    RS_DEBUG->print("RS_Text::update: missing font for letter( %s ), replaced it with QChar(0xfffd)",qPrintable(letterText));
                    letterText = QChar(0xfffd);
                }
//                if (font->findLetter(QString(data.text.at(i))) != NULL) {

                                        RS_DEBUG->print("RS_Text::update: insert a "
                                          "letter at pos: %f/%f", letterPos.x, letterPos.y);

                    RS_InsertData d(letterText,
                                    letterPos,
                                    RS_Vector(1.0, 1.0),
                                    0.0,
                                    1,1, RS_Vector(0.0,0.0),
                                    font->getLetterList(), RS2::NoUpdate);

                    RS_Insert* letter = new RS_Insert(this, d);
                    RS_Vector letterWidth;
                    letter->setPen(RS_Pen(RS2::FlagInvalid));
                    letter->setLayer(NULL);
                    letter->update();
                    letter->forcedCalculateBorders();

                                        // until 2.0.4.5:
                    //letterWidth = RS_Vector(letter->getSize().x, 0.0);
                                        // from 2.0.4.6:
                    letterWidth = RS_Vector(letter->getMax().x-letterPos.x, 0.0);
                    if (letterWidth.x < 0)
                        letterWidth.x = -letterSpace.x;

                    oneLine->addEntity(letter);

                    // next letter position:
                    letterPos += letterWidth;
                    letterPos += letterSpace;
//                }
            }
            break;
        }
    }

    double tt = updateAddLine(oneLine, lineCounter);
    if (data.valign == RS_MTextData::VABottom) {
        RS_Vector ot = RS_Vector(0.0,-tt).rotate(data.angle);
        RS_EntityContainer::move(ot);
    }

    usedTextHeight -= data.height*data.lineSpacingFactor*5.0/3.0
                      - data.height;
    forcedCalculateBorders();

    RS_DEBUG->print("RS_Text::update: OK");
}
コード例 #16
0
/**
* Creates a tangent between two circles or arcs.
* Out of the 4 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 circle1 1st circle or arc entity.
* @param circle2 2nd circle or arc entity.
*/
RS_Line* RS_Creation::createTangent2(const RS_Vector& coord,
                                     RS_Entity* circle1,
                                     RS_Entity* circle2) {
    RS_Line* ret = NULL;
    RS_Vector circleCenter1;
    RS_Vector circleCenter2;
    double circleRadius1 = 0.0;
    double circleRadius2 = 0.0;

    // check given entities:
    if (circle1==NULL || circle2==NULL ||
            ((circle1->rtti()!=RS2::EntityArc &&
              circle1->rtti()!=RS2::EntityEllipse &&
              circle1->rtti()!=RS2::EntityCircle) ||
             (circle2->rtti()!=RS2::EntityArc &&
              circle2->rtti()!=RS2::EntityEllipse &&
              circle2->rtti()!=RS2::EntityCircle) )) {

        return NULL;
    }

    QVector<RS_Line*> poss;
    //        for (int i=0; i<4; ++i) {
    //            poss[i] = NULL;
    //        }
    RS_LineData d;
    if( circle1->rtti() == RS2::EntityEllipse) {
        std::swap(circle1,circle2);//move Ellipse to the second place
    }
    circleCenter1=circle1->getCenter();
    circleRadius1=circle1->getRadius();
    circleCenter2=circle2->getCenter();
    circleRadius2=circle2->getRadius();
    if(circle2->rtti() != RS2::EntityEllipse) {
        //no ellipse

        // create all possible tangents:

        double angle1 = circleCenter1.angleTo(circleCenter2);
        double dist1 = circleCenter1.distanceTo(circleCenter2);

        if (dist1>1.0e-6) {
            // outer tangents:
            double dist2 = circleRadius2 - circleRadius1;
            if (dist1>dist2) {
                double angle2 = asin(dist2/dist1);
                double angt1 = angle1 + angle2 + M_PI/2.0;
                double angt2 = angle1 - angle2 - M_PI/2.0;
                RS_Vector offs1;
                RS_Vector offs2;

                offs1.setPolar(circleRadius1, angt1);
                offs2.setPolar(circleRadius2, angt1);

                d = RS_LineData(circleCenter1 + offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));


                offs1.setPolar(circleRadius1, angt2);
                offs2.setPolar(circleRadius2, angt2);

                d = RS_LineData(circleCenter1 + offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));
            }

            // inner tangents:
            double dist3 = circleRadius2 + circleRadius1;
            if (dist1>dist3) {
                double angle3 = asin(dist3/dist1);
                double angt3 = angle1 + angle3 + M_PI/2.0;
                double angt4 = angle1 - angle3 - M_PI/2.0;
                RS_Vector offs1;
                RS_Vector offs2;

                offs1.setPolar(circleRadius1, angt3);
                offs2.setPolar(circleRadius2, angt3);

                d = RS_LineData(circleCenter1 - offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));


                offs1.setPolar(circleRadius1, angt4);
                offs2.setPolar(circleRadius2, angt4);

                d = RS_LineData(circleCenter1 - offs1,
                                circleCenter2 + offs2);
                poss.push_back( new RS_Line(NULL, d));
            }

        }
    } else {
        //circle2 is Ellipse
        RS_Ellipse* e2=(RS_Ellipse*)circle2->clone();
//        RS_Ellipse* e2=new RS_Ellipse(NULL,RS_EllipseData(RS_Vector(4.,1.),RS_Vector(2.,0.),0.5,0.,0.,false));
//        RS_Ellipse  e3(NULL,RS_EllipseData(RS_Vector(4.,1.),RS_Vector(2.,0.),0.5,0.,0.,false));
//        RS_Ellipse* circle1=new RS_Ellipse(NULL,RS_EllipseData(RS_Vector(0.,0.),RS_Vector(1.,0.),1.,0.,0.,false));
        RS_Vector m0(circle1->getCenter());
//        std::cout<<"translation: "<<-m0<<std::endl;
        e2->move(-m0); //circle1 centered at origin

        double a,b;
        double a0(0.);
        if(circle1->rtti() != RS2::EntityEllipse) { //circle1 is either arc or circle
            a=fabs(circle1->getRadius());
            b=a;
            if(fabs(a)<RS_TOLERANCE) return NULL;
        } else { //circle1 is ellipse
            RS_Ellipse* e1=static_cast<RS_Ellipse*>(circle1);
            a0=e1->getAngle();
//            std::cout<<"rotation: "<<-a0<<std::endl;
            e2->rotate(-a0);//e1 major axis along x-axis
            a=e1->getMajorRadius();
            b=e1->getRatio()*a;
            if(fabs(a)<RS_TOLERANCE || fabs(b)<RS_TOLERANCE) return NULL;
        }
        RS_Vector factor1(1./a,1./b);
//        std::cout<<"scaling: factor1="<<factor1<<std::endl;
        e2->scale(RS_Vector(0.,0.),factor1);//circle1 is a unit circle
        factor1.set(a,b);
        double a2(e2->getAngle());
//        std::cout<<"rotation: a2="<<-a2<<std::endl;
        e2->rotate(-a2); //ellipse2 with major axis in x-axis direction
        a=e2->getMajorP().x;
        b=a*e2->getRatio();
        RS_Vector v(e2->getCenter());
//        std::cout<<"Center: (x,y)="<<v<<std::endl;


        std::vector<double> m(0,0.);
        m.push_back(1./(a*a)); //ma000
        m.push_back(1./(b*b)); //ma000
        m.push_back(v.y*v.y-1.); //ma100
        m.push_back(v.x*v.y); //ma101
        m.push_back(v.x*v.x-1.); //ma111
        m.push_back(2.*a*b*v.y); //mb10
        m.push_back(2.*a*b*v.x); //mb11
        m.push_back(a*a*b*b); //mc1

        auto&& vs0=RS_Math::simultaneousQuadraticSolver(m); //to hold solutions
        if (vs0.getNumber()<1) return NULL;
        for(int i=0; i<vs0.getNumber(); i++) {
//            std::cout<<"i="<<i<<"\n";
            RS_Vector vpec=vs0.get(i); //this holds ( a*sin(t), b*cos(t))
//            std::cout<<"solution "<<i<<" ="<<vpec<<std::endl;
            RS_Vector vpe2(e2->getCenter()+ RS_Vector(vpec.y/e2->getRatio(),vpec.x*e2->getRatio()));
            vpec.x *= -1.;//direction vector of tangent
            RS_Vector vpe1(vpe2 - vpec*(RS_Vector::dotP(vpec,vpe2)/vpec.squared()));
//            std::cout<<"vpe1.squared()="<<vpe1.squared()<<std::endl;
            RS_Line *l=new RS_Line(NULL,RS_LineData(vpe1,vpe2));
            l->rotate(a2);
            l->scale(factor1);
            l->rotate(a0);
            l->move(m0);
            poss.push_back(l);

        }
        delete e2;
        //debugging

    }
    // find closest tangent:
    if(poss.size()<1) return NULL;
    double minDist = RS_MAXDOUBLE;
    double dist;
    int idx = -1;
    for (int i=0; i<poss.size(); ++i) {
        if (poss[i]!=NULL) {
            poss[i]->getNearestPointOnEntity(coord,false,&dist);
//        std::cout<<poss.size()<<": i="<<i<<" dist="<<dist<<"\n";
            if (dist<minDist) {
                minDist = dist;
                idx = i;
            }
        }
    }
//idx=static_cast<int>(poss.size()*(random()/(double(1.0)+RAND_MAX)));
    if (idx!=-1) {
        RS_LineData d = poss[idx]->getData();
        for (int i=0; i<poss.size(); ++i) {
            if (poss[i]!=NULL) {
                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;
}
コード例 #17
0
ファイル: rs_mtext.cpp プロジェクト: dinkel/LibreCAD
/**
 * Used internally by update() to add a text line created with
 * default values and alignment to this text container.
 *
 * @param textLine The text line.
 * @param lineCounter Line number.
 *
 * @return  distance over the text base-line
 */
double RS_MText::updateAddLine(RS_EntityContainer* textLine, int lineCounter) {
    double ls =5.0/3.0;

    RS_DEBUG->print("RS_Text::updateAddLine: width: %f", textLine->getSize().x);

        //textLine->forcedCalculateBorders();
    //RS_DEBUG->print("RS_Text::updateAddLine: width 2: %f", textLine->getSize().x);

    // Move to correct line position:
    textLine->move(RS_Vector(0.0, -9.0 * lineCounter
                             * data.lineSpacingFactor * ls));

    if( ! RS_EntityContainer::autoUpdateBorders) {
        //only update borders when needed
        textLine->forcedCalculateBorders();
    }
    RS_Vector textSize = textLine->getSize();

        RS_DEBUG->print("RS_Text::updateAddLine: width 2: %f", textSize.x);

    // Horizontal Align:
    switch (data.halign) {
    case RS_MTextData::HACenter:
                RS_DEBUG->print("RS_Text::updateAddLine: move by: %f", -textSize.x/2.0);
        textLine->move(RS_Vector(-textSize.x/2.0, 0.0));
        break;

    case RS_MTextData::HARight:
        textLine->move(RS_Vector(-textSize.x, 0.0));
        break;

    default:
        break;
    }

    // Vertical Align:
    double vSize = getNumberOfLines()*9.0*data.lineSpacingFactor*ls
                   - (9.0*data.lineSpacingFactor*ls - 9.0);

    switch (data.valign) {
    case RS_MTextData::VAMiddle:
        textLine->move(RS_Vector(0.0, vSize/2.0));
        break;

    case RS_MTextData::VABottom:
        textLine->move(RS_Vector(0.0, vSize));
        break;

    default:
        break;
    }

    // Scale:
    textLine->scale(RS_Vector(0.0,0.0),
                    RS_Vector(data.height/9.0, data.height/9.0));

    textLine->forcedCalculateBorders();

    // Update actual text size (before rotating, after scaling!):
    if (textLine->getSize().x>usedTextWidth) {
        usedTextWidth = textLine->getSize().x;
    }

    usedTextHeight += data.height*data.lineSpacingFactor*ls;

    // Gets the distance over text base-line (before rotating, after scaling!):
    double textTail = textLine->getMin().y;

    // Rotate:
    textLine->rotate(RS_Vector(0.0,0.0), data.angle);

    // Move:
    textLine->move(data.insertionPoint);
    textLine->setPen(RS_Pen(RS2::FlagInvalid));
    textLine->setLayer(NULL);
    textLine->forcedCalculateBorders();

    addEntity(textLine);
    return textTail;
}
コード例 #18
0
ファイル: rs_math.cpp プロジェクト: Samsagax/LibreCAD
/* pow of vector components */
RS_Vector RS_Math::pow(RS_Vector vp, double y) {
        return RS_Vector(pow(vp.x,y),pow(vp.y,y));
}
コード例 #19
0
/**
 * @return Always an invalid vector.
 */
RS_Vector RS_Circle::getNearestEndpoint(const RS_Vector& /*coord*/, double* dist) {
    if (dist!=NULL) {
        *dist = RS_MAXDOUBLE;
    }
    return RS_Vector(false);
}
コード例 #20
0
/**
 * Handles command line events.
 */
void RS_EventHandler::commandEvent(RS_CommandEvent* e) {
    RS_DEBUG->print("RS_EventHandler::commandEvent");

    //RS_RegExp rex;
    RS_String cmd = e->getCommand();

    if (coordinateInputEnabled) {
        if (!e->isAccepted()) {
            // handle absolute cartesian coordinate input:
            if (cmd.contains(',') && cmd.at(0)!='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find(',');
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
                    bool ok1, ok2;
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
                    double x = RS_Math::eval(cmd.left(commaPos), &ok1);
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
                    double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 004");

                    if (ok1 && ok2) {
                        RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
                        RS_CoordinateEvent ce(RS_Vector(x,y));
                        RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
                    e->accept();
                }
            }
        }

        // handle relative cartesian coordinate input:
        if (!e->isAccepted()) {
            if (cmd.contains(',') && cmd.at(0)=='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find(',');
                    bool ok1, ok2;
                    double x = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
                    double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_CoordinateEvent ce(RS_Vector(x,y) +
                                              graphicView->getRelativeZero());
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
                    e->accept();
                }
            }
        }

        // handle absolute polar coordinate input:
        if (!e->isAccepted()) {
            if (cmd.contains('<') && cmd.at(0)!='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find('<');
                    bool ok1, ok2;
                    double r = RS_Math::eval(cmd.left(commaPos), &ok1);
                    double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_Vector pos;
                        pos.setPolar(r,RS_Math::deg2rad(a));
                        RS_CoordinateEvent ce(pos);
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
                    e->accept();
                }
            }
        }

        // handle relative polar coordinate input:
        if (!e->isAccepted()) {
            if (cmd.contains('<') && cmd.at(0)=='@') {
                if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                        !currentActions[actionIndex]->isFinished()) {
                    int commaPos = cmd.find('<');
                    bool ok1, ok2;
                    double r = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
                    double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                    if (ok1 && ok2) {
                        RS_Vector pos;
                        pos.setPolar(r,RS_Math::deg2rad(a));
                        RS_CoordinateEvent ce(pos +
                                              graphicView->getRelativeZero());
                        currentActions[actionIndex]->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY!=NULL) {
                            RS_DIALOGFACTORY->commandMessage(
                                "Expression Syntax Error");
                        }
                    }
                    e->accept();
                }
            }
        }
    }

    // send command event directly to current action:
    if (!e->isAccepted()) {
        if (actionIndex>=0 && currentActions[actionIndex]!=NULL &&
                !currentActions[actionIndex]->isFinished()) {
            currentActions[actionIndex]->commandEvent(e);
            e->accept();
        } else {
            if (defaultAction!=NULL) {
                defaultAction->commandEvent(e);
                //e->accept();
            }
        }
    }

    RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
}
コード例 #21
0
ファイル: rs_information.cpp プロジェクト: bert/LibreCAD
RS_VectorSolutions RS_Information::getIntersectionEllipseEllipse(RS_Ellipse* e1, RS_Ellipse* e2) {
    RS_VectorSolutions ret;

    if (e1==NULL || e2==NULL ) {
        return ret;
    }
    if (
        (e1->getCenter() - e2 ->getCenter()).squared() < RS_TOLERANCE2 &&
        (e1->getMajorP() - e2 ->getMajorP()).squared() < RS_TOLERANCE2 &&
        fabs(e1->getRatio() - e2 ->getRatio()) < RS_TOLERANCE
    ) { // overlapped ellipses, do not do overlap
        return ret;
    }
    RS_Ellipse ellipse01(NULL,e1->getData());

    RS_Ellipse *e01= & ellipse01;
    if( e01->getMajorRadius() < e01->getMinorRadius() ) e01->switchMajorMinor();
    RS_Ellipse ellipse02(NULL,e2->getData());
    RS_Ellipse *e02= &ellipse02;
    if( e02->getMajorRadius() < e02->getMinorRadius() ) e02->switchMajorMinor();
    //transform ellipse2 to ellipse1's coordinates
    RS_Vector shiftc1=- e01->getCenter();
    double shifta1=-e01->getAngle();
    e02->move(shiftc1);
    e02->rotate(shifta1);
    RS_Vector majorP2=e02->getMajorP();
    double a1=e01->getMajorRadius();
    double b1=e01->getMinorRadius();
    double x2=e02->getCenter().x,
           y2=e02->getCenter().y;
    double a2=e02->getMajorRadius();
    double b2=e02->getMinorRadius();

    if( e01->getMinorRadius() < RS_TOLERANCE || e01 -> getRatio()< RS_TOLERANCE) {
        // treate e01 as a line
        RS_LineData ldata0(RS_Vector(-a1,0.),RS_Vector(a1,0.));
        RS_Line *l0=new RS_Line(e1->getParent(),ldata0);
        ret= getIntersectionEllipseLine(l0, e02);
        ret.rotate(-shifta1);
        ret.move(-shiftc1);
        return ret;
    }
    if( e02->getMinorRadius() < RS_TOLERANCE || e02 -> getRatio()< RS_TOLERANCE) {
        // treate e02 as a line
        RS_LineData ldata0(RS_Vector(-a2,0.),RS_Vector(a2,0.));
        RS_Line *l0=new RS_Line(e1->getParent(),ldata0);
        l0->rotate(RS_Vector(0.,0.),e02->getAngle());
        l0->move(e02->getCenter());
        ret= getIntersectionEllipseLine(l0, e01);
        ret.rotate(-shifta1);
        ret.move(-shiftc1);
        return ret;
    }

    //ellipse01 equation:
    //	x^2/(a1^2) + y^2/(b1^2) - 1 =0
    double t2= - e02->getAngle();
    //ellipse2 equation:
    // ( (x - u) cos(t) - (y - v) sin(t))^2/a^2 + ( (x - u) sin(t) + (y-v) cos(t))^2/b^2 =1
    // ( cos^2/a^2 + sin^2/b^2) x^2 +
    // ( sin^2/a^2 + cos^2/b^2) y^2 +
    //  2 sin cos (1/b^2 - 1/a^2) x y +
    //  ( ( 2 v sin cos - 2 u cos^2)/a^2 - ( 2v sin cos + 2 u sin^2)/b^2) x +
    //  ( ( 2 u sin cos - 2 v sin^2)/a^2 - ( 2u sin cos + 2 v cos^2)/b^2) y +
    //  (u cos - v sin)^2/a^2 + (u sin + v cos)^2/b^2 -1 =0
    // detect whether any ellipse radius is zero
    double cs=cos(t2),si=sin(t2);
    double ucs=x2*cs,usi=x2*si,
           vcs=y2*cs,vsi=y2*si;
    double cs2=cs*cs,si2=1-cs2;
    double tcssi=2.*cs*si;
    double ia2=1./(a2*a2),ib2=1./(b2*b2);
    std::vector<double> m(0,0.);
    m.push_back( 1./(a1*a1)); //ma000
    m.push_back( 1./(b1*b1)); //ma011
    m.push_back(cs2*ia2 + si2*ib2); //ma100
    m.push_back(cs*si*(ib2 - ia2)); //ma101
    m.push_back(si2*ia2 + cs2*ib2); //ma111
    m.push_back(( y2*tcssi - 2.*x2*cs2)*ia2 - ( y2*tcssi+2*x2*si2)*ib2); //mb10
    m.push_back( ( x2*tcssi - 2.*y2*si2)*ia2 - ( x2*tcssi+2*y2*cs2)*ib2); //mb11
    m.push_back((ucs - vsi)*(ucs-vsi)*ia2+(usi+vcs)*(usi+vcs)*ib2 -1.); //mc1
    auto&& vs0=RS_Math::simultaneousQuadraticSolver(m);
    shifta1 = - shifta1;
    shiftc1 = - shiftc1;
    for(int i=0; i<vs0.getNumber(); i++) {
        RS_Vector vp=vs0.get(i);
        vp.rotate(shifta1);
        vp.move(shiftc1);
        ret.push_back(vp);
    }
    return ret;
}
コード例 #22
0
void RS_ActionPolylineTrim::mouseReleaseEvent(QMouseEvent* e) {
        if (e->button()==Qt::LeftButton) {
                RS_Vector cPoint;
                switch (getStatus()) {
                case ChooseEntity:
                        delEntity = catchEntity(e);
                        if (delEntity==NULL) {
                                RS_DIALOGFACTORY->commandMessage(tr("No Entity found."));
                        } else if (delEntity->rtti()!=RS2::EntityPolyline) {
                                RS_DIALOGFACTORY->commandMessage(
                                        tr("Entity must be a polyline."));
                        } else {
                                delEntity->setHighlighted(true);
                                graphicView->drawEntity(delEntity);
                                setStatus(SetSegment1);
////////////////////////////////////////2006/06/15
                                graphicView->redraw();
////////////////////////////////////////
                        }
                        break;

                case SetSegment1:
                        cPoint = snapPoint(e);
                        if (delEntity==NULL) {
                                RS_DIALOGFACTORY->commandMessage(tr("No Entity found."));
                        } else if (!cPoint.valid) {
                                RS_DIALOGFACTORY->commandMessage(tr("Specifying point is invalid."));
                        } else if (!delEntity->isPointOnEntity(cPoint)) {
                                RS_DIALOGFACTORY->commandMessage(
                                        tr("No Segment found on entity."));
                        }else{
                                Segment1 = NULL;
                                        double dist = graphicView->toGraphDX(snapRange)*0.9;
                                Segment1 =  (RS_AtomicEntity*)((RS_Polyline*)delEntity)->getNearestEntity( RS_Vector(graphicView->toGraphX(e->x()),
                                 graphicView->toGraphY(e->y())), &dist, RS2::ResolveNone);
                                if(Segment1 == NULL)
                                        break;
                                setStatus(SetSegment2);
                        }
                        break;
                case SetSegment2:
                        cPoint = snapPoint(e);
                        if (delEntity==NULL) {
                                RS_DIALOGFACTORY->commandMessage(tr("No Entity found."));
                        } else if (!cPoint.valid) {
                                RS_DIALOGFACTORY->commandMessage(tr("Specifying point is invalid."));
                        } else if (!delEntity->isPointOnEntity(cPoint)) {
                                RS_DIALOGFACTORY->commandMessage(
                                        tr("No Segment found on entity."));
                        }else{
                                Segment2 = NULL;
                                        double dist = graphicView->toGraphDX(snapRange)*0.9;
                                Segment2 =  (RS_AtomicEntity*)((RS_Polyline*)delEntity)->getNearestEntity( RS_Vector(graphicView->toGraphX(e->x()),
                                 graphicView->toGraphY(e->y())), &dist, RS2::ResolveNone);
                                if(Segment2 == NULL)
                                        break;
                                deleteSnapper();
                                trigger();
                        }
                        break;

                default:
                        break;
                }
        } else if (e->button()==Qt::RightButton) {
                deleteSnapper();
                if (delEntity!=NULL) {
                        delEntity->setHighlighted(false);
                        graphicView->drawEntity(delEntity);
////////////////////////////////////////2006/06/15
                        graphicView->redraw();
////////////////////////////////////////
                }
                init(getStatus()-1);
        }
}
コード例 #23
0
void Plugin_Entity::move(QPointF offset){
    entity->move( RS_Vector(offset.x(), offset.y()) );
}
コード例 #24
0
ファイル: rs_dimaligned.cpp プロジェクト: DietmarK/LC2DK
void RS_DimAligned::rotate(const RS_Vector& center, const double& angle) {
   rotate(center,RS_Vector(angle));
}
コード例 #25
0
void Plugin_Entity::scale(QPointF center, QPointF factor){
    entity->scale( RS_Vector(center.x(), center.y()),
                RS_Vector(factor.x(), factor.y()) );
}
コード例 #26
0
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double patternOffset) {
    if (painter==NULL || view==NULL) {
        return;
    }

    if (getPen().getLineType()==RS2::SolidLine ||
            isSelected() ||
            view->getDrawingMode()==RS2::ModePreview) {

        painter->drawLine(view->toGui(getStartpoint()),
                          view->toGui(getEndpoint()));
    } else {
        double styleFactor = getStyleFactor(view);
        if (styleFactor<0.0) {
            painter->drawLine(view->toGui(getStartpoint()),
                              view->toGui(getEndpoint()));
            return;
        }

        // Pattern:
        RS_LineTypePattern* pat;
        if (isSelected()) {
            pat = &patternSelected;
        } else {
            pat = view->getPattern(getPen().getLineType());
        }
        if (pat==NULL) {
            RS_DEBUG->print(RS_Debug::D_WARNING,
                            "RS_Line::draw: Invalid line pattern");
            return;
        }

        // Pen to draw pattern is always solid:
        RS_Pen pen = painter->getPen();

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

        // index counter
        int i;

        // line data:
        double length = getLength();
        double angle = getAngle1();

        // pattern segment length:
        double patternSegmentLength = 0.0;

        // create pattern:
        RS_Vector* dp = new RS_Vector[pat->num];

        for (i=0; i<pat->num; ++i) {
            dp[i] = RS_Vector(cos(angle) * fabs(pat->pattern[i] * styleFactor),
                              sin(angle) * fabs(pat->pattern[i] * styleFactor));

            patternSegmentLength += fabs(pat->pattern[i] * styleFactor);
        }

        // handle pattern offset:
        int m;
        if (patternOffset<0.0) {
            m = (int)ceil(patternOffset / patternSegmentLength);
        }
        else {
            m = (int)floor(patternOffset / patternSegmentLength);
        }

        patternOffset -= (m*patternSegmentLength);
        //if (patternOffset<0.0) {
        //	patternOffset+=patternSegmentLength;
        //}
        //RS_DEBUG->print("pattern. offset: %f", patternOffset);
        RS_Vector patternOffsetVec;
        patternOffsetVec.setPolar(patternOffset, angle);

        double tot=patternOffset;
        i=0;
        bool done = false;
        bool cutStartpoint, cutEndpoint, drop;
        RS_Vector curP=getStartpoint()+patternOffsetVec;

        do {
            cutStartpoint = false;
            cutEndpoint = false;
            drop = false;

            // line segment (otherwise space segment)
            if (pat->pattern[i]>0.0) {
                // drop the whole pattern segment line:
                if (tot+pat->pattern[i]*styleFactor < 0.0) {
                    drop = true;
                }
                else {
                    // trim startpoint of pattern segment line to line startpoint
                    if (tot < 0.0) {
                        cutStartpoint = true;
                    }
                    // trim endpoint of pattern segment line to line endpoint
                    if (tot+pat->pattern[i]*styleFactor > length) {
                        cutEndpoint = true;
                    }
                }

                if (drop) {
                    // do nothing
                }
                else {
                    RS_Vector p1 = curP;
                    RS_Vector p2 = curP + dp[i];

                    if (cutStartpoint) {
                        p1 = getStartpoint();
                    }
                    if (cutEndpoint) {
                        p2 = getEndpoint();
                    }

                    painter->drawLine(view->toGui(p1),
                                      view->toGui(p2));
                }
            }
            curP+=dp[i];
            tot+=fabs(pat->pattern[i]*styleFactor);
            //RS_DEBUG->print("pattern. tot: %f", tot);
            done=tot>length;

            i++;
            if (i>=pat->num) {
                i=0;
            }
        } while(!done);

        delete[] dp;

    }
}
コード例 #27
0
ファイル: rs_dimension.cpp プロジェクト: RoboMod/LibreCAD
/**
 * 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) {

    // text height (DIMTXT)
    double dimtxt = getTextHeight();
    // text distance to line (DIMGAP)
    double dimgap = getDimensionLineGap();

    // length of dimension line:
    double distance = p1.distanceTo(p2);

    // do we have to put the arrows outside of the line?
    bool outsideArrows = (distance<getArrowSize()*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(getArrowSize()*2, arrowAngle2);
        dimensionLine->setStartpoint(p1 + dir);
        dimensionLine->setEndpoint(p2 - dir);
    }
double dimtsz=getTickSize();
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,
                          getArrowSize());
        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,
                          getArrowSize());
        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);
        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);
}
コード例 #28
0
ファイル: rs_eventhandler.cpp プロジェクト: dinkel/LibreCAD
/**
 * Handles command line events.
 */
void RS_EventHandler::commandEvent(RS_CommandEvent* e) {
    RS_DEBUG->print("RS_EventHandler::commandEvent");
    QString cmd = e->getCommand();

    // allow using command line as a calculator
    if (!e->isAccepted())  {
        if(cliCalculator(cmd)) {
            e->accept();
            return;
        }
    }

    if (coordinateInputEnabled) {
        if (!e->isAccepted()) {

            if(hasAction()){
                // handle absolute cartesian coordinate input:
                if (cmd.contains(',') && cmd.at(0)!='@') {

                    int commaPos = cmd.indexOf(',');
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 001");
                    bool ok1, ok2;
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 002");
                    double x = RS_Math::eval(cmd.left(commaPos), &ok1);
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 003a");
                    double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);
                    RS_DEBUG->print("RS_EventHandler::commandEvent: 004");

                    if (ok1 && ok2) {
                        RS_DEBUG->print("RS_EventHandler::commandEvent: 005");
                        RS_CoordinateEvent ce(RS_Vector(x,y));
                        RS_DEBUG->print("RS_EventHandler::commandEvent: 006");
                        currentActions.last()->coordinateEvent(&ce);
                    } else {
                        if (RS_DIALOGFACTORY) {
                            RS_DIALOGFACTORY->commandMessage(
                                        "Expression Syntax Error");
                        }
                    }
                    e->accept();
                }

                // handle relative cartesian coordinate input:
                if (!e->isAccepted()) {
                    if (cmd.contains(',') && cmd.at(0)=='@') {
                        int commaPos = cmd.indexOf(',');
                        bool ok1, ok2;
                        double x = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
                        double y = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                        if (ok1 && ok2) {
                            RS_CoordinateEvent ce(RS_Vector(x,y) +
                                                  graphicView->getRelativeZero());

                            currentActions.last()->coordinateEvent(&ce);
                            //                            currentActions[actionIndex]->coordinateEvent(&ce);
                        } else {
                            if (RS_DIALOGFACTORY) {
                                RS_DIALOGFACTORY->commandMessage(
                                            "Expression Syntax Error");
                            }
                        }
                        e->accept();
                    }
                }

                // handle absolute polar coordinate input:
                if (!e->isAccepted()) {
                    if (cmd.contains('<') && cmd.at(0)!='@') {
                        int commaPos = cmd.indexOf('<');
                        bool ok1, ok2;
                        double r = RS_Math::eval(cmd.left(commaPos), &ok1);
                        double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                        if (ok1 && ok2) {
							RS_Vector pos{
								RS_Vector::polar(r,RS_Math::deg2rad(a))};
                            RS_CoordinateEvent ce(pos);
                            currentActions.last()->coordinateEvent(&ce);
                        } else {
                            if (RS_DIALOGFACTORY) {
                                RS_DIALOGFACTORY->commandMessage(
                                            "Expression Syntax Error");
                            }
                        }
                        e->accept();
                    }
                }

                // handle relative polar coordinate input:
                if (!e->isAccepted()) {
                    if (cmd.contains('<') && cmd.at(0)=='@') {
                        int commaPos = cmd.indexOf('<');
                        bool ok1, ok2;
                        double r = RS_Math::eval(cmd.mid(1, commaPos-1), &ok1);
                        double a = RS_Math::eval(cmd.mid(commaPos+1), &ok2);

                        if (ok1 && ok2) {
							RS_Vector pos = RS_Vector::polar(r,RS_Math::deg2rad(a));
                            RS_CoordinateEvent ce(pos +
                                                  graphicView->getRelativeZero());
                            currentActions.last()->coordinateEvent(&ce);
                        } else {
                            if (RS_DIALOGFACTORY) {
                                RS_DIALOGFACTORY->commandMessage(
                                            "Expression Syntax Error");
                            }
                        }
                        e->accept();
                    }
                }

                // send command event directly to current action:
                if (!e->isAccepted()) {
//                    std::cout<<"RS_EventHandler::commandEvent(RS_CommandEvent* e): sending cmd("<<qPrintable(e->getCommand()) <<") to action: "<<currentActions.last()->rtti()<<std::endl;
                    currentActions.last()->commandEvent(e);
                }
            }else{
            //send the command to default action
                if (defaultAction) {
                    defaultAction->commandEvent(e);
                }
            }
            // do not accept command here. Actions themselves should be responsible to accept commands
//            e->accept();
        }
    }

    RS_DEBUG->print("RS_EventHandler::commandEvent: OK");
}
コード例 #29
0
void RS_ActionDrawFlower::reset() {
    data = RS_CircleData(RS_Vector(false), 0.0);
}
コード例 #30
0
ファイル: rs_solid.cpp プロジェクト: LibreCAD/LibreCAD
/**
 * Constructor for a solid with 3 corners.
 */
RS_SolidData::RS_SolidData(const RS_Vector& corner1,
                           const RS_Vector& corner2,
                           const RS_Vector& corner3):
    corner{{corner1, corner2, corner3, RS_Vector(false)}}
{
}