/** * \return List of RLines describing this spline. */ QList<QSharedPointer<RShape> > RSpline::getExploded(int segments) const { if (!exploded.isEmpty() && segments==-1) { return exploded; } //qDebug() << "RSpline::getExploded: segments: " << segments; //RDebug::printBacktrace("getExploded: "); //##boundingBox = RBox(); updateInternal(); exploded.clear(); if (!isValid()) { //qWarning() << "RSpline::getExploded: invalid spline"; return exploded; } if (segments==-1) { segments = 8; } double tMin = getTMin(); double tMax = getTMax(); double step = getTDelta() / (controlPoints.size() * segments); RVector p1; RVector prev = RVector::invalid; for (double t = tMin; t<tMax+(step/2.0); t+=step) { double tc = qMin(t, tMax); p1 = getPointAt(tc); if (RMath::isNaN(p1.x) || RMath::isNaN(p1.y)) { continue; } if (prev.isValid()) { RLine* line = new RLine(prev, p1); exploded.append(QSharedPointer<RShape>(line)); } prev = p1; //##boundingBox.growToInclude(p1); } p1 = getEndPoint(); if (!RMath::isNaN(p1.x) && !RMath::isNaN(p1.y)) { if (prev.isValid()) { RLine* line = new RLine(prev, p1); // prevent zero length line at the end: if (line->getLength()>1.0e-4) { exploded.append(QSharedPointer<RShape>(line)); } } } return exploded; }
RVector RPolyline::getVectorTo(const RVector& point, bool limited, double strictRange) const { RVector ret = RVector::invalid; QList<QSharedPointer<RShape> > sub = getExploded(); QList<QSharedPointer<RShape> >::iterator it; for (it=sub.begin(); it!=sub.end(); ++it) { RVector v = (*it)->getVectorTo(point, limited, strictRange); if (v.isValid() && (!ret.isValid() || v.getMagnitude()<ret.getMagnitude())) { ret = v; } } return ret; }
bool RCircle::move(const RVector& offset) { if (!offset.isValid() || offset.getMagnitude() < RS::PointTolerance) { return false; } center += offset; return true; }
/** * \return Point on this shape that is closest to p. Based on getVectorTo. */ RVector RShape::getClosestPointOnShape(const RVector& p, bool limited) const { RVector dv = getVectorTo(p, limited); if (!dv.isValid()) { return RVector::invalid; } return p - dv; }
/** * \return Shortest distance from this shape to the given point. * Based on \ref getVectorTo. */ double RShape::getDistanceTo(const RVector& point, bool limited) const { RVector v = getVectorTo(point, limited); if (v.isValid()) { return v.getMagnitude(); } return RNANDOUBLE; }
void ROrthoGrid::paintGridLines(const RVector& space, const RBox& box, bool meta) { if (!space.isValid()) { return; } // updates cache if necessary: getProjection(); isIsometric(); RVector min = box.getCorner1(); RVector max = box.getCorner2(); double deltaX = max.x - min.x; double deltaY = max.y - min.y; if (deltaX / space.x > 1e3 || deltaY / space.y > 1e3) { return; } double dx = deltaY / tan(M_PI/6); if (isometric) { min.x -= dx; max.x += dx; } int c; double x; for (x=min.x, c=0; x<max.x; x+=space.x, c++) { //int x2 = RMath::mround(x/space.x); //if (!isometric || c%2==0) { if (isometric) { if (projection==RS::IsoTop || projection==RS::IsoRight) { view.paintGridLine(RLine(RVector(x, min.y), RVector(x+dx, max.y))); } if (projection==RS::IsoTop || projection==RS::IsoLeft) { view.paintGridLine(RLine(RVector(x, min.y), RVector(x-dx, max.y))); } // vertical grid lines: if (projection==RS::IsoRight || projection==RS::IsoLeft) { view.paintGridLine(RLine(RVector(x, min.y), RVector(x, max.y))); view.paintGridLine(RLine(RVector(x-space.x/2, min.y), RVector(x-space.x/2, max.y))); } } else { view.paintGridLine(RLine(RVector(x, min.y), RVector(x, max.y))); } //} } // horizontal lines: if (!isometric) { for (double y=min.y; y<max.y; y+=space.y) { view.paintGridLine(RLine(RVector(min.x, y), RVector(max.x, y))); } } }
/** * \return The shortest distance from this entity to the given point. */ double REntityData::getDistanceTo(const RVector& point, bool limited, double range, bool draft) const { Q_UNUSED(range); Q_UNUSED(draft); RVector v = getVectorTo(point, limited); if (v.isValid()) { return v.getMagnitude(); } return RNANDOUBLE; }
/** * \return The distance vector from this entity to the given point. * * \param point the point to which the distance was measured * * \param limited: If true, an invalid vector is returned if the * closest point on the entity is outside of the entity (e.g. in * the extension line of a line or outside the start / end angle * of an arc). */ RVector REntityData::getVectorTo(const RVector& point, bool limited) const { RVector ret = RVector::invalid; QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { shapes.at(i)->to2D(); RVector r = shapes.at(i)->getVectorTo(point, limited); if (!ret.isValid() || r.getMagnitude()<ret.getMagnitude()) { ret = r; } } return ret; }
/** * Called on every repaint of a view to update snap related information. * \param painter QPainter for the view in screen coordinates. * \param snap Current snap. */ void REventHandler::updateSnapInfo(QPainter* painter, RSnap* snap, RSnapRestriction* restriction) { if (snap==NULL) { return; } RVector pos = snap->getLastSnap(); if (!pos.isValid()) { return; } RVector posRestriction = RVector::invalid; if (restriction!=NULL) { posRestriction = restriction->getLastSnap(); } QString text = ""; switch (snap->getStatus()) { // case RSnap::Free: // text = tr("Free"); // break; case RSnap::Grid: text = tr("Grid"); break; case RSnap::Endpoint: text = tr("End"); break; case RSnap::OnEntity: text = tr("On Entity"); break; case RSnap::Perpendicular: text = tr("Perpendicular"); break; case RSnap::Tangential: text = tr("Tangential"); break; case RSnap::Center: text = tr("Center"); break; case RSnap::Middle: text = tr("Middle"); break; case RSnap::Intersection: text = tr("Intersection"); break; case RSnap::Reference: text = tr("Reference"); break; default: break; } drawSnapLabel(painter, pos, posRestriction, text); }
/** * Maps the given model position to the grid. */ RVector ROrthoGrid::snapToGrid(const RVector& positionUcs) { RDocumentInterface* documentInterface = view.getDocumentInterface(); if (documentInterface==NULL) { return RVector::invalid; } RVector sp = spacing; if (!sp.isValid()) { sp = metaSpacing; if (isometric) { sp /= 2; } } int x = RMath::mround(positionUcs.x / sp.x); int y = RMath::mround(positionUcs.y / sp.y); int z = RMath::mround(positionUcs.z / sp.z); // closest grid point is not available in isometric grid, // find closest available grid point: if (isometric && (x+y)%2!=0) { int cx, cy; double minDist = RMAXDOUBLE; double dist; for (int ix=-1; ix<=1; ix++) { for (int iy=-1; iy<=1; iy++) { if (qAbs(ix) + qAbs(iy)!=1) { continue; } cx = RMath::mround(positionUcs.x / sp.x) + ix; cy = RMath::mround(positionUcs.y / sp.y) + iy; dist = positionUcs.getDistanceTo(RVector(cx*sp.x, cy*sp.y)); if (dist<minDist) { x = cx; y = cy; minDist = dist; } } } } RVector gridPositionUcs = RVector( x * sp.x, y * sp.y, z * sp.z ); RUcs ucs = documentInterface->getCurrentUcs(); return ucs.mapFromUcs(gridPositionUcs); }
RVector RSpline::getVectorTo(const RVector& point, bool limited, double strictRange) const { RVector ret = RVector::invalid; // TODO: not implemented in Teigha: // if (splineProxy!=NULL) { // RVector p = splineProxy->getClosestPointOnShape(*this, point, limited); // if (p.isValid()) { // ret = p - point; // } // } // else { QList<QSharedPointer<RShape> > sub = getExploded(); QList<QSharedPointer<RShape> >::iterator it; for (it=sub.begin(); it!=sub.end(); ++it) { RVector v = (*it)->getVectorTo(point, limited, strictRange); if (v.isValid() && (!ret.isValid() || v.getMagnitude()<ret.getMagnitude())) { ret = v; } } // } return ret; }
/** * \return Closest point to \c point on this entity. Used for snap to * points on entity. */ RVector REntityData::getClosestPointOnEntity(const RVector& point, double range, bool limited) const { Q_UNUSED(range) RVector ret = RVector::invalid; double minDist = RMAXDOUBLE; QList<QSharedPointer<RShape> > shapes = getShapes(); for (int i=0; i<shapes.size(); i++) { RVector r = shapes.at(i)->getClosestPointOnShape(point, limited); double dist = r.getDistanceTo(point); if (!ret.isValid() || dist<minDist) { ret = r; minDist = dist; } } return ret; }
void RDimAlignedData::recomputeDefinitionPoint( const RVector& oldExtPoint1, const RVector& oldExtPoint2, const RVector& newExtPoint1, const RVector& newExtPoint2) { RLine dLine(oldExtPoint1, oldExtPoint2); double d = dLine.getDistanceTo(definitionPoint, false); RS::Side s = dLine.getSideOfPoint(definitionPoint); double a = newExtPoint1.getAngleTo(newExtPoint2); if (s==RS::LeftHand) { a+=M_PI/2.0; } else { a-=M_PI/2.0; } RVector v = RVector::createPolar(d, a); RVector dp = newExtPoint1 + v; if (dp.isValid()) { definitionPoint = dp; } }
void ROrthoGrid::paintGridPoints(const RVector& space, const RBox& box) { if (!space.isValid()) { return; } RVector min = box.getCorner1(); RVector max = box.getCorner2(); if ((max.x - min.x) / space.x > 1e3 || (max.y - min.y) / space.y > 1e3) { return; } RVector gridPointUcs; int x, y; for (gridPointUcs.x = min.x; gridPointUcs.x < max.x; gridPointUcs.x += space.x) { x = RMath::mround(gridPointUcs.x/space.x); for (gridPointUcs.y = min.y; gridPointUcs.y < max.y; gridPointUcs.y += space.y) { y = RMath::mround(gridPointUcs.y/space.y); if (!isometric || (x+y)%2==0) { view.paintGridPoint(gridPointUcs); } } } }
RVector REllipse::getVectorTo(const RVector& point, bool limited, double strictRange) const { Q_UNUSED(strictRange) RVector ret = RVector::invalid; double ang = getAngle(); //double dDistance = RMAXDOUBLE; bool swap = false; bool majorSwap = false; RVector normalized = (point - center).rotate(-ang); // special case: point in line with major axis: if (fabs(normalized.getAngle()) < RS::AngleTolerance || fabs(normalized.getAngle()) > 2*M_PI-RS::AngleTolerance) { ret = RVector(getMajorRadius(), 0.0); //dDistance = ret.distanceTo(normalized); } else if (fabs(normalized.getAngle()-M_PI) < RS::AngleTolerance) { ret = RVector(-getMajorRadius(), 0.0); //dDistance = ret.distanceTo(normalized); } else { double dU = normalized.x; double dV = normalized.y; double dA = getMajorRadius(); double dB = getMinorRadius(); double dEpsilon = 1.0e-8; // iteration maximum int iMax = 32; double rdX = 0.0; double rdY = 0.0; if (dA<dB) { double dum = dA; dA = dB; dB = dum; dum = dU; dU = dV; dV = dum; majorSwap = true; } if (dV<0.0) { dV*=-1.0; swap = true; } // initial guess: double dT = dB*(dV - dB); // newton's method: int i; for (i = 0; i < iMax; i++) { double dTpASqr = dT + dA*dA; double dTpBSqr = dT + dB*dB; double dInvTpASqr = 1.0/dTpASqr; double dInvTpBSqr = 1.0/dTpBSqr; double dXDivA = dA*dU*dInvTpASqr; double dYDivB = dB*dV*dInvTpBSqr; double dXDivASqr = dXDivA*dXDivA; double dYDivBSqr = dYDivB*dYDivB; double dF = dXDivASqr + dYDivBSqr - 1.0; if (fabs(dF) < dEpsilon) { // f(t0) is very close to zero: rdX = dXDivA*dA; rdY = dYDivB*dB; break; } double dFDer = 2.0*(dXDivASqr*dInvTpASqr + dYDivBSqr*dInvTpBSqr); double dRatio = dF/dFDer; if ( fabs(dRatio) < dEpsilon ) { // t1-t0 is very close to zero: rdX = dXDivA*dA; rdY = dYDivB*dB; break; } dT += dRatio; } if (i == iMax) { // failed to converge: //dDistance = RMAXDOUBLE; ret = RVector::invalid; } else { //double dDelta0 = rdX - dU; //double dDelta1 = rdY - dV; //dDistance = sqrt(dDelta0*dDelta0 + dDelta1*dDelta1); ret = RVector(rdX, rdY); } } if (ret.isValid()) { if (swap) { ret.y*=-1.0; } if (majorSwap) { double dum = ret.x; ret.x = ret.y; ret.y = dum; } ret = (ret.rotate(ang) + center); if (limited) { double a1 = center.getAngleTo(getStartPoint()); double a2 = center.getAngleTo(getEndPoint()); double a = center.getAngleTo(ret); if (!RMath::isAngleBetween(a, a1, a2, reversed)) { ret = RVector::invalid; } } } /* if (dist!=NULL) { if (ret.valid) { *dist = dDistance; } else { *dist = RS_MAXDOUBLE; } } if (entity!=NULL) { if (ret.valid) { *entity = this; } else { *entity = NULL; } } */ return point - ret; }
RS::Orientation RPolyline::getOrientation() const { if (!isGeometricallyClosed()) { return RS::Any; } RVector minV = RVector::invalid; QSharedPointer<RDirected> shapeBefore; QSharedPointer<RDirected> shapeAfter; QSharedPointer<RShape> shape; QSharedPointer<RDirected> previousShape = getSegmentAt(countSegments()-1).dynamicCast<RDirected>(); // find minimum vertex (lower left corner): QList<QSharedPointer<RShape> > segments = getExploded(); for (int i=0; i<segments.length(); i++) { shape = getSegmentAt(i); if (shape.isNull()) { continue; } QSharedPointer<RDirected> directed = shape.dynamicCast<RDirected>(); if (directed.isNull()) { continue; } RVector v = directed->getStartPoint(); if (!minV.isValid() || v.x<minV.x || (v.x==minV.x && v.y<minV.y)) { minV = v; shapeBefore = previousShape; shapeAfter = directed; } previousShape = directed; } double l; RVector p; QSharedPointer<RArc> arcBefore = shapeBefore.dynamicCast<RArc>(); if (!arcBefore.isNull()) { l = arcBefore->getLength(); p = arcBefore->getPointsWithDistanceToEnd(l/10, RS::FromStart)[0]; shapeBefore = QSharedPointer<RLine>(new RLine(p, arcBefore->getEndPoint())); } QSharedPointer<RArc> arcAfter = shapeAfter.dynamicCast<RArc>(); if (!arcAfter.isNull()) { l = arcAfter->getLength(); p = arcAfter->getPointsWithDistanceToEnd(l/10, RS::FromEnd)[0]; shapeAfter = QSharedPointer<RLine>(new RLine(arcAfter->getStartPoint(), p)); } double xa = shapeBefore->getStartPoint().x; double ya = shapeBefore->getStartPoint().y; double xb = shapeAfter->getStartPoint().x; double yb = shapeAfter->getStartPoint().y; double xc = shapeAfter->getEndPoint().x; double yc = shapeAfter->getEndPoint().y; double det = (xb-xa) * (yc-ya) - (xc-xa) * (yb-ya); if (det<0.0) { // clockwise: return RS::CW; } else { // counter-clockwise: return RS::CCW; } }
void ROrthoGrid::paintRuler(RRuler& ruler, qreal devicePixelRatio) { RDocument* doc = view.getDocument(); if (doc == NULL) { return; } RS::Unit unit = doc->getUnit(); RS::LinearFormat linearFormat = doc->getLinearFormat(); // use grid spacing if available or auto grid spacing: RVector localSpacing = spacing; if (!localSpacing.isValid() || (autoSpacing.isValid() && autoSpacing.getMagnitude2d() < localSpacing.getMagnitude2d())) { localSpacing = autoSpacing; } // use meta grid spacing if available or auto meta grid spacing: RVector localMetaSpacing = metaSpacing; if (!localMetaSpacing.isValid() || (autoMetaSpacing.isValid() && autoMetaSpacing.getMagnitude2d() < localMetaSpacing.getMagnitude2d())) { //localMetaSpacing = autoMetaSpacing; } //if (!localMetaSpacing.isValid()) { // qDebug() << "no local meta spacing"; // return; //} if (localSpacing.getMagnitude()<1.0e-6 || localMetaSpacing.getMagnitude()<1.0e-6) { //qDebug() << "local (meta) spacing too small"; return; } RVector min = gridBox.getCorner1(); RVector max = gridBox.getCorner2(); bool isHorizontal = ruler.getOrientation() == Qt::Horizontal; double tickSpacing; //if (!RUnit::isMetric(doc->getUnit())) { if (isFractionalFormat(linearFormat) && !RUnit::isMetric(unit)) { if (isHorizontal) { tickSpacing = localSpacing.x; } else { tickSpacing = localSpacing.y; } } else { if (isHorizontal) { tickSpacing = localMetaSpacing.x; } else { tickSpacing = localMetaSpacing.y; } if (view.mapDistanceToView(tickSpacing) >= 80) { tickSpacing /= 10; } else if (view.mapDistanceToView(tickSpacing) >= 30) { tickSpacing /= 5; } else if (view.mapDistanceToView(tickSpacing) >= 20) { tickSpacing /= 2; } } // ideal tick spacing in pixels: int pSpacing = (int) ceil(view.mapDistanceToView(tickSpacing)); QString l1 = RUnit::getLabel(isHorizontal ? min.x : min.y, *doc, false, true); QString l2 = RUnit::getLabel(isHorizontal ? max.x : max.y, *doc, false, true); int labelWidth = std::max( QFontMetrics(ruler.getFont()).boundingRect(l1).width(), QFontMetrics(ruler.getFont()).boundingRect(l2).width()) + 15; // smallest displayable distance between labels in steps (ticks): int minLabelStep = 1; if (pSpacing>0) { minLabelStep = labelWidth / pSpacing + 1; } int labelStep = minLabelStep; //if (!RUnit::isMetric(doc->getUnit())) { if (isFractionalFormat(linearFormat) && !RUnit::isMetric(unit)) { // non metric double f = 1.0/128; do { if (localMetaSpacing.isValid()) { if (isHorizontal) { labelStep = RMath::mround(localMetaSpacing.x / localSpacing.x) * f; } else { labelStep = RMath::mround(localMetaSpacing.y / localSpacing.y) * f; } } else { labelStep = (int)f; } f = f * 2; if (f>65536) { labelStep = -1; } } while (labelStep < minLabelStep && labelStep>=0); } else { // metric if (labelStep >= 3 && labelStep <= 4) { labelStep = 5; } else if (labelStep >= 6 && labelStep <= 9) { labelStep = 10; } else if (labelStep >= 11 && labelStep <= 19) { labelStep = 20; } else if (labelStep >= 21 && labelStep <= 99) { labelStep = 100; } } if (labelStep<0) { return; } if (labelStep<1) { labelStep = 1; } double minPos; double maxPos; if (isHorizontal) { minPos = (floor(view.mapFromView(RVector(0, 0)).x / (labelStep * tickSpacing))-1) * (labelStep * tickSpacing); maxPos = (ceil(view.mapFromView(RVector(view.getWidth(), 0)).x / (labelStep * tickSpacing))+1) * (labelStep * tickSpacing); } else { minPos = (floor(view.mapFromView(RVector(0, view.getHeight())).y / (labelStep * tickSpacing))-1) * (labelStep * tickSpacing); maxPos = (ceil(view.mapFromView(RVector(0, 0)).y / (labelStep * tickSpacing))+1) * (labelStep * tickSpacing); } if ((maxPos - minPos) / tickSpacing > 1e3) { return; } int c; double p; for (c = 0, p = minPos; p < maxPos; p += tickSpacing, ++c) { bool hasLabel = c % labelStep == 0; double v; if (isHorizontal) { v = view.mapToView(RVector(p, 0)).x; } else { v = view.mapToView(RVector(0, p)).y; } ruler.paintTick(v*devicePixelRatio, hasLabel, hasLabel ? RUnit::getLabel(p, *doc, false, true, true) : QString()); } }
QList<QSharedPointer<RShape> > RDimAngularData::getShapes(const RBox& queryBox, bool ignoreComplex, bool segment) const { Q_UNUSED(queryBox) Q_UNUSED(ignoreComplex) Q_UNUSED(segment) QSharedPointer<RBlockReferenceEntity> dimBlockReference = getDimensionBlockReference(); if (!dimBlockReference.isNull()) { return dimBlockReference->getShapes(queryBox, ignoreComplex); } QList<QSharedPointer<RShape> > ret; double dimexo = getDimexo(); double dimexe = getDimexe(); double dimtxt = getDimtxt(); double dimgap = getDimgap(); double dimasz = getDimasz(); // find out center: RVector center = getCenter(); if (!center.isValid()) { return ret; } double ang1 = 0.0; double ang2 = 0.0; bool reversed = false; RVector p1; RVector p2; getAngles(ang1, ang2, reversed, p1, p2); double rad = dimArcPosition.getDistanceTo(center); RLine line; RVector dir; double len; double dist; // 1st extension line: dist = center.getDistanceTo2D(p1); len = rad - dist + dimexe; dir.setPolar(1.0, ang1); line = RLine(center + dir*dist + dir*dimexo, center + dir*dist + dir*len); ret.append(QSharedPointer<RShape>(new RLine(line))); // 2nd extension line: dist = center.getDistanceTo2D(p2); len = rad - dist + dimexe; dir.setPolar(1.0, ang2); line = RLine(center + dir*dist + dir*dimexo, center + dir*dist + dir*len); ret.append(QSharedPointer<RShape>(new RLine(line))); // Create dimension line (arc): RArc arc(center, rad, ang1, ang2, reversed); ret.append(QSharedPointer<RShape>(new RArc(arc))); // length of dimension arc: double distance = arc.getLength(); // do we have to put the arrows outside of the arc? bool outsideArrows = (distance<dimasz*2); // arrow angles: double arrowAngle1, arrowAngle2; double arrowAng; if (rad>1.0e-6) { arrowAng = getDimasz() / rad; } else { arrowAng = 0.0; } if (outsideArrows) { arrowAngle1 = arc.getDirection1(); arrowAngle2 = arc.getDirection2(); } else { RVector v1, v2; if (!arc.isReversed()) { v1.setPolar(rad, arc.getStartAngle()+arrowAng); } else { v1.setPolar(rad, arc.getStartAngle()-arrowAng); } v1+=arc.getCenter(); arrowAngle1 = arc.getStartPoint().getAngleTo(v1); if (!arc.isReversed()) { v2.setPolar(rad, arc.getEndAngle()-arrowAng); } else { v2.setPolar(rad, arc.getEndAngle()+arrowAng); } v2+=arc.getCenter(); arrowAngle2 = arc.getEndPoint().getAngleTo(v2); arrowAngle1 = arrowAngle1+M_PI; arrowAngle2 = arrowAngle2+M_PI; } // Arrows: //RTriangle arrow = RTriangle::createArrow(arc.getStartPoint(), arrowAngle1, dimasz); QList<QSharedPointer<RShape> > arrow = getArrow(arc.getStartPoint(), arrowAngle1); ret.append(arrow); //arrow = RTriangle::createArrow(arc.getEndPoint(), arrowAngle2, dimasz); arrow = getArrow(arc.getEndPoint(), arrowAngle2); ret.append(arrow); //ret.append(QSharedPointer<RShape>(new RTriangle(arrow))); //RVector oldMot = textPosition; //textPosition = RVector(0,0); //defaultAngle = 0.0; //dimLineLength = RNANDOUBLE; //getTextData(); //textPosition = oldMot; RVector textPos = arc.getMiddlePoint(); double dimAngle1 = textPos.getAngleTo(arc.getCenter())-M_PI/2.0; if (!autoTextPos) { dimAngle1 = textPositionCenter.getAngleTo(arc.getCenter())-M_PI/2.0; } RVector distV; double textAngle; // rotate text so it's readable from the bottom or right (ISO) // quadrant 1 & 4 if (dimAngle1>M_PI/2.0*3.0+0.001 || dimAngle1<M_PI/2.0+0.001) { distV.setPolar(dimgap + dimtxt/2, dimAngle1+M_PI/2.0); textAngle = dimAngle1; } // quadrant 2 & 3 else { distV.setPolar(dimgap + dimtxt/2, dimAngle1-M_PI/2.0); textAngle = dimAngle1+M_PI; } if (!autoTextPos) { textPos = textPositionCenter; } else { // move text away from dimension line: textPos+=distV; textPositionCenter = textPos; } defaultAngle = textAngle; //getTextData(); //textData.rotate(textAngle, RVector(0,0)); //textData.move(textPos); return ret; }
void REventHandler::drawSnapLabel(QPainter* painter, const RVector& pos, const RVector& posRestriction, const QString& text) { RVector p = graphicsView->mapToView(pos); RVector pr = RVector::invalid; if (posRestriction.isValid()) { pr = graphicsView->mapToView(posRestriction); } RColor color = RSettings::getColor("GraphicsViewColors/TextLabelColor", RColor(249,198,31)); painter->setPen(color); QFont font = RSettings::getSnapLabelFont(); font.setPointSizeF(font.pointSizeF()*graphicsView->getDevicePixelRatio()); QFontMetrics fm(font); painter->setFont(font); int offset = 5 * graphicsView->getDevicePixelRatio(); if (!text.isEmpty()) { painter->drawText( p.x + offset, p.y + offset, fm.width(text)+10, fm.height()+10, Qt::AlignHCenter | Qt::AlignVCenter, text, NULL); } painter->drawEllipse(p.x-offset, p.y-offset, offset*2, offset*2); // restriction position: if (pr.isSane()) { painter->drawLine(pr.x, pr.y-offset, pr.x+offset, pr.y); painter->drawLine(pr.x+offset, pr.y, pr.x, pr.y+offset); painter->drawLine(pr.x, pr.y+offset, pr.x-offset, pr.y); painter->drawLine(pr.x-offset, pr.y, pr.x, pr.y-offset); } // display distance/angle: int display = RSettings::getIntValue("DisplaySettings/DisplayDistanceAngle", 0); if (display == 0) { return; } RDocumentInterface* di = graphicsView->getDocumentInterface(); RDocument* doc = graphicsView->getDocument(); RVector relativeZero = di->getRelativeZero(); double dist, angle; if (posRestriction.isSane()) { dist = relativeZero.getDistanceTo(posRestriction); angle = relativeZero.getAngleTo(posRestriction); } else { dist = relativeZero.getDistanceTo(pos); angle = relativeZero.getAngleTo(pos); } int lp = doc->getLinearPrecision(); QString distStr = RUnit::doubleToString(dist, lp); angle = RMath::rad2deg(angle); int ap = doc->getAnglePrecision(); QString angStr = RUnit::doubleToString(angle, ap); QString sep = RSettings::getStringValue("Input/PolarCoordinateSeparator", "<"); color = RSettings::getColor("GraphicsViewColors/MeasurementToolsColor", RColor(155,220,112)); painter->setPen(color); QString displayText; switch (display) { case 0: displayText = ""; break; case 1: displayText = distStr + sep + angStr + QChar(0x00b0); break; case 2: displayText = distStr; break; case 3: displayText = angStr + QChar(0x00b0); break; default: displayText = ""; } if (!displayText.isEmpty()) { painter->drawText( p.x + offset, p.y - 3*offset - fm.height(), fm.width(displayText)+10, fm.height()+10, Qt::AlignHCenter | Qt::AlignVCenter, displayText, NULL); } }