コード例 #1
0
QList<RVector> RShape::getIntersectionPointsCC(const RCircle& circle1,
        const RCircle& circle2) {

    QList<RVector> res;
    bool tangent = false;

    RVector c1 = circle1.getCenter();
    RVector c2 = circle2.getCenter();

    double r1 = circle1.getRadius();
    double r2 = circle2.getRadius();

    RVector u = c2 - c1;

    // the two circles (almost) touch in one point (tangent):
    if (RMath::fuzzyCompare(u.getMagnitude(), r1+r2, 1.0e-6)) {
        u.setMagnitude2d(r1);
        res.append(c1 + u);
        tangent = true;
        return res;
    }

    // concentric
    if (u.getMagnitude() < RS::PointTolerance) {
        return res;
    }

    RVector v = RVector(u.y, -u.x);

    double s, t1, t2, term;

    s = 1.0/2.0 * ((r1*r1 - r2*r2)/(RMath::pow(u.getMagnitude(), 2.0)) + 1.0);

    term = (r1*r1)/(RMath::pow(u.getMagnitude(), 2.0)) - s*s;

    // no intersection:
    if (term < 0.0) {
        return res;
    }

    // one or two intersections:
    t1 = sqrt(term);
    t2 = -sqrt(term);

    RVector sol1 = c1 + u*s + v*t1;
    RVector sol2 = c1 + u*s + v*t2;

    if (sol1.equalsFuzzy(sol2, 1.0e-4)) {
        res.append(sol1);
        tangent = true;
    }
    else {
        res.append(sol1);
        res.append(sol2);
    }

    return res;
}
コード例 #2
0
ファイル: RCircle.cpp プロジェクト: Alpha-Kand/qcad
RVector RCircle::getVectorTo(const RVector& point, bool /*limited*/) const {
    RVector v = point - center;

    // point is at the center of the circle, infinite solutions:
    if (v.getMagnitude()<RS::PointTolerance) {
        return RVector::invalid;
    }

    return RVector::createPolar(v.getMagnitude() - radius, v.getAngle());
}
コード例 #3
0
ファイル: REntityData.cpp プロジェクト: VixMobile/qcad
/**
 * \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;
}
コード例 #4
0
ファイル: RPolyline.cpp プロジェクト: eric3361229/qcad
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;
}
コード例 #5
0
ファイル: RCircle.cpp プロジェクト: Alpha-Kand/qcad
bool RCircle::move(const RVector& offset) {
    if (!offset.isValid() || offset.getMagnitude() < RS::PointTolerance) {
        return false;
    }
    center += offset;
    return true;
}
コード例 #6
0
QList<RVector> RShape::getIntersectionPointsLT(const RLine& line1,
        const RTriangle& triangle2, bool limited) {

    QList<RVector> res;

    RVector normal = triangle2.getNormal();

    if (normal.getMagnitude() < 1.0e-12) {
        return res;
    }

    if (line1.getLength() < 1.0e-12) {
        return res;
    }

    double t = RVector::getDotProduct(normal, triangle2.getCorner(2) - line1.getStartPoint())
            / RVector::getDotProduct(normal, (line1.getEndPoint() - line1.getStartPoint()));

    // check if intersection point is on the line:
    if (limited && (t < 0.0 || t > 1.0)) {
        return res;
    }

    // intersection point:
    RVector ip = line1.getStartPoint() + (line1.getEndPoint() - line1.getStartPoint()) * t;

    // check if intersection point is inside the triangle:
    if (!limited || triangle2.isPointInTriangle(ip)) {
        res.push_back(ip);
    }

    return res;
}
コード例 #7
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;
}
コード例 #8
0
ファイル: REntityData.cpp プロジェクト: VixMobile/qcad
/**
 * \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;
}
コード例 #9
0
ファイル: RArc.cpp プロジェクト: Alpha-Kand/qcad
RVector RArc::getVectorTo(const RVector& point, bool limited) const {
    double angle = center.getAngleTo(point);
    if (limited
            && !RMath::isAngleBetween(angle, startAngle, endAngle, reversed)) {
        return RVector::invalid;
    }

    RVector v = point - center;
    return RVector::createPolar(v.getMagnitude() - radius, v.getAngle());
}
コード例 #10
0
ファイル: RSpline.cpp プロジェクト: Jackieee/qcad
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;
}
コード例 #11
0
ファイル: RTriangle.cpp プロジェクト: VixMobile/qcad
double RTriangle::getDistanceTo(const RVector& point, bool limited) const {

    RVector normal = getNormal();
    double d = getD();
    double distance = (normal.x * point.x + normal.y * point.y + normal.z
            * point.z + d) / (normal.getMagnitude());

    if (!limited
            || isPointInTriangle(point - normal.getUnitVector() * distance)) {
        return distance;
    }

    return RMAXDOUBLE;
}
コード例 #12
0
ファイル: ROrthoGrid.cpp プロジェクト: Jackieee/qcad
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());
    }
}
コード例 #13
0
ファイル: REllipse.cpp プロジェクト: Jackieee/qcad
/**
 * Sets the minor point relative to the center point.
 */
void REllipse::setMinorPoint(const RVector& p) {
    double angle = RMath::getNormalizedAngle(p.getAngle() - M_PI/2.0);
    majorPoint.setPolar(getMajorRadius(), angle);
    setRatio(p.getMagnitude() / getMajorRadius());
}
コード例 #14
0
QList<RVector> RShape::getIntersectionPointsLC(const RLine& line1,
        const RCircle& circle2, bool limited) {
    QList<RVector> res;

    RVector vLineCenter = line1.getVectorTo(circle2.getCenter(), false);
    double dist = vLineCenter.getMagnitude();

    // special case: arc touches line (tangent):
    if (fabs(dist - circle2.getRadius()) < 1.0e-4) {
        res.append(circle2.getCenter() - vLineCenter);
        // ret.setTangent(true);
        return res;
    }

    RVector p = line1.getStartPoint();
    RVector d = line1.getEndPoint() - line1.getStartPoint();
    if (d.getMagnitude() < 1.0e-6) {
        return res;
    }

    RVector delta = p - circle2.getCenter();

    // root term:
    double term = RMath::pow(RVector::getDotProduct(d, delta), 2.0)
                  - RMath::pow(d.getMagnitude(), 2.0)
                  * (RMath::pow(delta.getMagnitude(), 2.0) - RMath::pow(circle2.getRadius(), 2.0));

    // no intersection:
    if (term<0.0) {
        return res;
    }

    // one or two intersections:
    double t1 = (- RVector::getDotProduct(d, delta) + sqrt(term))
                / RMath::pow(d.getMagnitude(), 2.0);
    double t2;
    bool tangent = false;

    // only one intersection:
    if (fabs(term) < RS::PointTolerance) {
        t2 = t1;
        tangent = true;
    }

    // two intersections
    else {
        t2 = (-RVector::getDotProduct(d, delta) - sqrt(term))
             / RMath::pow(d.getMagnitude(), 2.0);
    }

    RVector sol1;
    RVector sol2 = RVector::invalid;

    sol1 = p + d * t1;

    if (!tangent) {
        sol2 = p + d * t2;
    }

    if (!limited || line1.isOnShape(sol1)) {
        res.append(sol1);
    }
    if (sol2.isValid()) {
        if (!limited || line1.isOnShape(sol2)) {
            res.append(sol2);
        }
    }
    // ret.setTangent(tangent);

    return res;
}