Пример #1
0
bool RExporter::exportLinetypeShape(QList<RPainterPath>& pps, const RLine& line, double total, double length, double angle, const RVector& cursor) {
    RVector min = RPainterPath::getMinList(pps);
    RVector max = RPainterPath::getMaxList(pps);
    bool isCursorOnLine = line.isOnShape(cursor);
    double diffBefore = total+min.x;
    double diffAfter = total+max.x-length;
    bool shapeOutsideBefore = diffBefore < -RS::PointTolerance;
    bool shapeOutsideAfter = diffAfter > RS::PointTolerance;
    if (isCursorOnLine && (!shapeOutsideBefore && !shapeOutsideAfter)) {
        exportPainterPaths(pps, angle, cursor);
        return true;
    }
    else {
        if (shapeOutsideBefore) {
            // check if first shape is not entirely before the start point of the line:
            if (total + max.x < 0.0) {
                return false;
            }
            RLine l = line;
            if (fabs(total+max.x)<length) {
                RVector p = RVector(
                            cos(angle) * fabs(total+max.x),
                            sin(angle) * fabs(total+max.x)
                            );
                l.endPoint = l.startPoint + p;
            }
            exportLineSegment(l, angle);
            return true;
        }
        if (shapeOutsideAfter) {
            // check if last shape is not entirely after the end point of the line:
            if (total + min.x > length) {
                return false;
            }
            RLine l = line;
            if (fabs(total+min.x)>0.0) {
                RVector p = RVector(
                            cos(angle) * fabs(total+min.x),
                            sin(angle) * fabs(total+min.x)
                            );
                l.startPoint = l.startPoint + p;
            }
            exportLineSegment(l, angle);
            return true;
        }

        return false;
    }
}
Пример #2
0
QList<RVector> RShape::getIntersectionPointsLL(const RLine& line1,
        const RLine& line2, bool limited1, bool limited2) {
    QList<RVector> res;
    double a1 = line1.endPoint.y - line1.startPoint.y;
    double b1 = line1.startPoint.x - line1.endPoint.x;
    double c1 = a1 * line1.startPoint.x + b1 * line1.startPoint.y;

    double a2 = line2.endPoint.y - line2.startPoint.y;
    double b2 = line2.startPoint.x - line2.endPoint.x;
    double c2 = a2 * line2.startPoint.x + b2 * line2.startPoint.y;

    double det = a1 * b2 - a2 * b1;
    if (fabs(det) < 1.0e-6) {
        return res;
    } else {
        RVector v((b2 * c1 - b1 * c2) / det, (a1 * c2 - a2 * c1) / det);

        if ((!limited1 || line1.isOnShape(v)) && (!limited2 || line2.isOnShape(v))) {
            res.append(v);
            return res;
        }
    }
    return res;
}
Пример #3
0
QList<RVector> RShape::getIntersectionPointsLE(const RLine& line1,
        const REllipse& ellipse2, bool limited) {

    QList<RVector> res;

    // find out if line1 is (almost) a tangent:
    QList<RLine> tangents = ellipse2.getTangents(line1.getMiddlePoint());
    for (int i=0; i<tangents.length(); i++) {
        double a = tangents[i].getAngle();
        double ad1 = fabs(RMath::getAngleDifference180(a, line1.getDirection1()));
        double ad2 = fabs(RMath::getAngleDifference180(a, line1.getDirection2()));

        if (ad1 < 1.0e-2 || ad2 < 1.0e-2) {
            res.append(tangents[i].getEndPoint());

            // no need to continue: max. one tangent possible:
            return res;
        }
    }

    // rotate into normal position:
    double ang = ellipse2.getAngle();

    double rx = ellipse2.getMajorRadius();
    double ry = ellipse2.getMinorRadius();
    RVector center = ellipse2.getCenter();
    RVector a1 = line1.getStartPoint();
    a1.rotate(-ang, center);
    RVector a2 = line1.getEndPoint();
    a2.rotate(-ang, center);
    RVector origin = a1;
    RVector dir = a2-a1;
    RVector diff = origin - center;
    RVector mDir = RVector(dir.x/(rx*rx), dir.y/(ry*ry));
    RVector mDiff = RVector(diff.x/(rx*rx), diff.y/(ry*ry));

    double a = RVector::getDotProduct(dir, mDir);
    double b = RVector::getDotProduct(dir, mDiff);
    double c = RVector::getDotProduct(diff, mDiff) - 1.0;
    double d = b*b - a*c;

    RVector res1 = RVector::invalid;
    RVector res2 = RVector::invalid;

    if (d < 0) {
        // no solution
    } else if ( d > 0 ) {
        double root = sqrt(d);
        double t_a = (-b - root) / a;
        double t_b = (-b + root) / a;

        res1 = a1.getLerp(a2, t_a).rotate(ang, center);
        res2 = a1.getLerp(a2, t_b).rotate(ang, center);
    } else {
        double t = -b/a;
        if ( 0 <= t && t <= 1 ) {
            // one solution:
            res1 = a1.getLerp(a2, t).rotate(ang, center);
        } else {
            // no solution
        }
    }

    if (res1.isValid()) {
        if (!limited || (line1.isOnShape(res1) && ellipse2.isOnShape(res1))) {
            res.append(res1);
        }
    }
    if (res2.isValid()) {
        if (!limited || (line1.isOnShape(res2) && ellipse2.isOnShape(res2))) {
            res.append(res2);
        }
    }

    return res;
}
Пример #4
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;
}