示例#1
0
void RPainterPathExporter::exportLineSegment(const RLine& line, double angle) {
    if (line.getLength()<RS::PointTolerance) {
        if (exportZeroLinesAsPoints) {
            path.addPoint(line.getStartPoint());
        }
        else {
            // Qt won't export a zero length line as point:
            // e.g. dot in a dash/dot line:
            RVector startPoint = line.startPoint - RVector::createPolar(0.01, angle);
            RVector endPoint = line.endPoint + RVector::createPolar(0.01, angle);
            path.moveTo(startPoint);
            path.lineTo(endPoint);
//            path.moveTo(line.getStartPoint()-RVector(0.01,0));
//            path.lineTo(line.getEndPoint()+RVector(0.01, 0));
//            path.moveTo(line.getStartPoint()-RVector(0,0.01));
//            path.lineTo(line.getEndPoint()+RVector(0, 0.01));
        }
    }
    else {
        if (!path.isAtPosition(line.getStartPoint())) {
            path.moveTo(line.getStartPoint());
        }
        path.lineTo(line.getEndPoint());
    }
}
示例#2
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;
}
示例#3
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;
}
示例#4
0
void RPainterPathExporter::exportLineSegment(const RLine& line) {
    if (line.getLength()<RS::PointTolerance) {
        path.addPoint(line.getStartPoint());
    }
    else {
        path.moveTo(line.getStartPoint());
        path.lineTo(line.getEndPoint());
    }
}
示例#5
0
void RSpline::appendToExploded(const RLine& line) const {
    if (line.getLength()<1.0e-6) {
        return;
    }

    if (!exploded.isEmpty()) {
        // compare angle of this sement with last segment and
        // modify last segment if angle is the same (straight line):
        QSharedPointer<RLine> prev = exploded.last().dynamicCast<RLine>();
        if (!prev.isNull()) {
            if (RMath::fuzzyCompare(prev->getAngle(), prev->getStartPoint().getAngleTo(line.getEndPoint()))) {
                prev->setEndPoint(line.getEndPoint());
                return;
            }
        }
    }

    exploded.append(QSharedPointer<RShape>(new RLine(line)));
}
示例#6
0
void RGraphicsSceneQt::exportLineSegment(const RLine& line, double angle) {
    Q_ASSERT(currentPainterPath.isValid());

    if (line.getLength()<RS::PointTolerance && !RMath::isNaN(angle)) {
        // Qt won't export a zero length line as point:
        RVector startPoint = line.startPoint - RVector::createPolar(0.01, angle);
        RVector endPoint = line.endPoint + RVector::createPolar(0.01, angle);
        currentPainterPath.moveTo(startPoint);
        currentPainterPath.lineTo(endPoint);
        return;
    }

    // add new painter path with current entity ID:
    if ((currentPainterPath.currentPosition() - QPointF(line.startPoint.x, line.startPoint.y)).manhattanLength() > RS::PointTolerance) {
        currentPainterPath.moveTo(line.startPoint);
    }

    currentPainterPath.lineTo(line.endPoint);
}
示例#7
0
void RExporter::exportLine(const RLine& line, double offset) {
    if (!line.isValid()) {
        return;
    }

    double length = line.getLength();

    if (length>1e100 || length<RS::PointTolerance) {
        return;
    }

    RLinetypePattern p = getLinetypePattern();

    // continuous line or
    // we are in draft mode or
    // QCAD is configured to show screen based line patterns
    if (!p.isValid() || p.getNumDashes() == 1 || draftMode || screenBasedLinetypes) {
        exportLineSegment(line);
        return;
    }

    p.scale(getPatternFactor());
    double patternLength = p.getPatternLength();
    

    // avoid huge number of small segments due to very fine 
    // pattern or long lines:
    if (patternLength<RS::PointTolerance || length / patternLength > 5000) {
        exportLineSegment(line);
        return;
    }

    double angle = line.getAngle();
    RVector* vp = NULL;
    vp = new RVector[p.getNumDashes()];
    for (int i = 0; i < p.getNumDashes(); ++i) {
        vp[i] = RVector(cos(angle) * fabs(p.getDashLengthAt(i)),
                        sin(angle) * fabs(p.getDashLengthAt(i)));
    }

    bool optimizeEnds = false;
    if (RMath::isNaN(offset)) {
        offset = getPatternOffset(length, p);
        optimizeEnds = true;
    }
    else {
        double num = ceil(offset / patternLength);
        offset -= num * patternLength;
    }

    bool done = false;
    int i = 0;
    RVector cursor(line.getStartPoint() + RVector::createPolar(offset, angle));
    double total = offset;
    bool dashFound = false;
    bool gapFound = false;
    RVector p1 = line.getStartPoint();
    RVector p2 = p1;

    do {
        if (dashFound && !gapFound) {
            // don't shoot over end of line:
            if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) {
                if (optimizeEnds) {
                    exportLineSegment(RLine(p1, line.endPoint));
                }
                else {
                    exportLineSegment(RLine(p1, p2));
                }
                break;
            }
            exportLineSegment(RLine(p1, p2));
        }

        // dash, no gap. note that a dash can have a length of 0.0 (point):
        if (p.getDashLengthAt(i) > -RS::PointTolerance) {
            // check if we're on the line already:
            if (total + p.getDashLengthAt(i) > 0) {
                p1 = cursor;

                // no gap at the beginning of the line:
                if (total < 0 || (!dashFound && optimizeEnds)) {
                    p1 = line.startPoint;
                }

                p2 = cursor + vp[i];
                if (!p2.equalsFuzzy(line.startPoint, 1.0e-6)) {
                    dashFound = true;
                }
            }
            gapFound = false;
        }

        // gap:
        else {
            gapFound = true;
        }

        cursor += vp[i];
        total += fabs(p.getDashLengthAt(i));

        done = total > length;

        ++i;
        if (i >= p.getNumDashes()) {
            i = 0;
        }
    } while (!done);

    if (!gapFound || !dashFound) {
        if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) {
            if (optimizeEnds || (total>length && !gapFound)) {
                exportLineSegment(RLine(p1, line.endPoint));
            }
            else {
                exportLineSegment(RLine(p1, p2));
            }
        } else {
            exportLineSegment(RLine(p1, p2));
        }
    }

    delete[] vp;
}
示例#8
0
double RExporter::exportLine(const RLine& line, double offset) {
    double ret = RNANDOUBLE;

    if (!line.isValid()) {
        return ret;
    }

    double length = line.getLength();

    if (length>1e100 || length<RS::PointTolerance) {
        return ret;
    }

    double angle = line.getAngle();

    // continuous line or
    // we are in draft mode or
    // QCAD is configured to show screen based line patterns
    if (draftMode || screenBasedLinetypes || twoColorSelectedMode) {
        exportLineSegment(line, angle);
        return ret;
    }

    RLinetypePattern p = getLinetypePattern();
    if (!p.isValid() || p.getNumDashes() <= 1) {
        exportLineSegment(line, angle);
        return ret;
    }

    p.scale(getLineTypePatternScale(p));
    double patternLength = p.getPatternLength();

    // avoid huge number of small segments due to very fine 
    // pattern or long lines:
    if (patternLength<RS::PointTolerance || length / patternLength > RSettings::getDashThreshold()) {
        exportLineSegment(line, angle);
        return ret;
    }

    RVector* vp = NULL;
    vp = new RVector[p.getNumDashes()];
    for (int i = 0; i < p.getNumDashes(); ++i) {
        vp[i] = RVector(cos(angle) * fabs(p.getDashLengthAt(i)),
                        sin(angle) * fabs(p.getDashLengthAt(i)));
    }

    if (RMath::isNaN(offset)) {
        offset = p.getPatternOffset(length);
    }
    else {
        double num = ceil(offset / patternLength);
        offset -= num * patternLength;
    }

    bool done = false;
    int i = 0;
    RVector cursor(line.getStartPoint() + RVector::createPolar(offset, angle));
    double total = offset;
    double nextTotal;
    bool isGap = false;
    RLine dash;

    do {
        double dashLength = p.getDashLengthAt(i);
        nextTotal = total + fabs(dashLength);
        //qDebug() << "total: " << total;
        //qDebug() << "nextTotal: " << nextTotal;

        // dash, no gap. note that a dash can have a length of 0.0 (point):
        if (dashLength > -RS::PointTolerance) {
            isGap = false;
        }

        // gap:
        else {
            isGap = true;
        }

        // check if we're on the line already
        // (since we might start before the line due to pattern offset):
        if (nextTotal > 0.0) {
            dash = RLine(cursor, cursor + vp[i]);

            if (!isGap) {
                // fist part is gap, then dash
                ret = -nextTotal;
            }
            else {
                // fist part is dash, then gap
                ret = nextTotal;
            }

            // shorten at start of line:
            if (total < 0.0 /*&& nextTotal > 0.0*/) {
                dash.startPoint = line.startPoint;
                ret = RNANDOUBLE;
            }

            // shorten at end of line:
            if (/*total < length &&*/ nextTotal >= length - 1.0e-6) {
                dash.endPoint = line.endPoint;
                ret = RINFDOUBLE;
            }

            if (!isGap) {
                exportLineSegment(dash, angle);
                ret = nextTotal;
            }
        }

        cursor += vp[i];
        total = nextTotal;

        done = total > length;

        // export shape (zigzag, text, etc.) at end of dash / gap:
        if (p.hasShapeAt(i)) {
            QList<RPainterPath> pps = p.getShapeAt(i);
            exportLinetypeShape(pps, line, total, length, angle, cursor);
        }

        ++i;
        if (i >= p.getNumDashes()) {
            i = 0;
        }
    } while (!done);

    delete[] vp;

    return ret;
}