/** * @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)); }
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)); }
/** * Constructor for num solutions. */ RS_VectorSolutions::RS_VectorSolutions(int num): vector(num, RS_Vector(false)) ,tangent(false) { }
/*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; } }
void Plugin_Entity::rotate(QPointF center, double angle){ entity->rotate( RS_Vector(center.x(), center.y()) , angle); }
void RS_Polyline::rotate(const RS_Vector& center, const double& angle) { rotate(center, RS_Vector(angle)); }
RS_Vector RS_Circle::getNearestDist(double /*distance*/, bool /*startp*/) { return RS_Vector(false); }
void LC_ActionDrawCircle2PR::reset() { data->reset(); data->radius=0.; point1 = RS_Vector(false); point2 = RS_Vector(false); }
void RS_ActionPolylineAdd::init(int status) { RS_ActionInterface::init(status); addEntity = addSegment = NULL; addCoord = RS_Vector(false); }
void RS_ActionDrawCircle2P::reset() { data.reset(); point1 = RS_Vector(false); point2 = RS_Vector(false); }
/** * 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"); }
void QG_CoordinateWidget::setGraphic(RS_Graphic* graphic) { this->graphic = graphic; setCoordinates(RS_Vector(0.0,0.0), RS_Vector(0.0,0.0), true); }
/** * 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; }
/** * 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(); }
/** * 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"); }
/** * 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; }
/** * 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; }
/* 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)); }
/** * @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); }
/** * 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"); }
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; }
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); } }
void Plugin_Entity::move(QPointF offset){ entity->move( RS_Vector(offset.x(), offset.y()) ); }
void RS_DimAligned::rotate(const RS_Vector& center, const double& angle) { rotate(center,RS_Vector(angle)); }
void Plugin_Entity::scale(QPointF center, QPointF factor){ entity->scale( RS_Vector(center.x(), center.y()), RS_Vector(factor.x(), factor.y()) ); }
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; } }
/** * 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); }
/** * 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"); }
void RS_ActionDrawFlower::reset() { data = RS_CircleData(RS_Vector(false), 0.0); }
/** * 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)}} { }