Exemple #1
0
/**
 * \param polylineGen True: use pattern along whole polyline, False: pattern per segment.
 */
void RExporter::exportPolyline(const RPolyline& polyline, bool polylineGen, double offset) {
    RLinetypePattern p = getLinetypePattern();

    bool continuous = false;
    if (getEntity() == NULL || !p.isValid() || p.getNumDashes() <= 1 || draftMode || screenBasedLinetypes || twoColorSelectedMode) {
        continuous = true;
    }

    if (!continuous) {
        p.scale(getLineTypePatternScale(p));

        if (RMath::isNaN(offset)) {
            double length = polyline.getLength();
            offset = p.getPatternOffset(length);
        }
    }

    if (polylineGen) {
        // pattern along whole polyline:
        exportExplodable(polyline, offset);
    }
    else {
        // pattern for each individual segment:
        for (int i=0; i<polyline.countSegments(); i++) {
            QSharedPointer<RShape> shape = polyline.getSegmentAt(i);
            QSharedPointer<RLine> line = shape.dynamicCast<RLine>();
            if (!line.isNull()) {
                RExporter::exportLine(*line);
            }
            QSharedPointer<RArc> arc = shape.dynamicCast<RArc>();
            if (!arc.isNull()) {
                RExporter::exportArc(*arc);
            }
        }
    }
}
Exemple #2
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;
}
Exemple #3
0
void RExporter::exportSpline(const RSpline& spline, double offset) {
    RLinetypePattern p = getLinetypePattern();

    bool continuous = false;
    if (getEntity() == NULL || !p.isValid() || p.getNumDashes() <= 1 || draftMode || screenBasedLinetypes || twoColorSelectedMode) {
        continuous = true;
    }

    p.scale(getLineTypePatternScale(p));
    double patternLength = p.getPatternLength();
    if (patternLength<RS::PointTolerance || spline.getLength() / patternLength > RSettings::getDashThreshold()) {
        continuous = true;
    }

    if (!continuous) {
        if (getEntity()!=NULL && (getEntity()->getType()!=RS::EntitySpline || RSpline::hasProxy())) {
            // we have a spline proxy:
            RShapesExporter(*this, QList<QSharedPointer<RShape> >() << QSharedPointer<RShape>(spline.clone()), offset);
        }
        else {
            // fallback if we don't have a spline proxy:
            p.scale(getLineTypePatternScale(p));

            if (RMath::isNaN(offset)) {
                double length = spline.getLength();
                offset = p.getPatternOffset(length);
            }
            exportExplodable(spline, offset);
        }
    }
    else {
        // version <= 3.0.0 was (line interpolation):
        //exportExplodable(spline, offset);

        // performance improvement (using real splines):
        RPainterPath pp;
        pp.setPen(currentPen);
        pp.setInheritPen(true);
        pp.addSpline(spline);
        exportPainterPaths(QList<RPainterPath>() << pp);
    }

    /*
    RLinetypePattern p = getLinetypePattern();
    p.scale(getLineTypePatternScale(p));

    if (RMath::isNaN(offset)) {
        double length = spline.getLength();
        offset = p.getPatternOffset(length);
    }

    double currentOffset = offset;
    QList<QSharedPointer<RShape> > sub = spline.getExploded();
    QList<QSharedPointer<RShape> >::iterator it;
    for (it=sub.begin(); it!=sub.end(); ++it) {
        QSharedPointer<RLine> line = (*it).dynamicCast<RLine>();
        if (!line.isNull()) {
            exportLine(*line.data(), currentOffset);
            currentOffset -= line->getLength();
        }

        QSharedPointer<RArc> arc = (*it).dynamicCast<RArc>();
        if (!arc.isNull()) {
            exportArc(*arc.data(), currentOffset);
            currentOffset -= arc->getLength();
        }
    }
    */
}