Example #1
0
/**
 * \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;
}
Example #2
0
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;
}
Example #3
0
bool RCircle::move(const RVector& offset) {
    if (!offset.isValid() || offset.getMagnitude() < RS::PointTolerance) {
        return false;
    }
    center += offset;
    return true;
}
Example #4
0
/**
 * \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;
}
Example #5
0
/**
 * \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;
}
Example #6
0
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)));
        }
    }
}
Example #7
0
/**
 * \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;
}
Example #8
0
/**
 * \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;
}
Example #9
0
/**
 * 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);
}
Example #10
0
/**
 * 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);
}
Example #11
0
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;
}
Example #12
0
/**
 * \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;
}
Example #13
0
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;
    }
}
Example #14
0
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);
            }
        }
    }
}
Example #15
0
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;
}
Example #16
0
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;
    }
}
Example #17
0
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());
    }
}
Example #18
0
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;
}
Example #19
0
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);
    }
}