QScriptValue
        REcmaLinetypePattern::getPatternLength
        (QScriptContext* context, QScriptEngine* engine) 
        
        {
            //REcmaHelper::functionStart("REcmaLinetypePattern::getPatternLength", context, engine);
            //qDebug() << "ECMAScript WRAPPER: REcmaLinetypePattern::getPatternLength";
            //QCoreApplication::processEvents();

            QScriptValue result = engine->undefinedValue();
            
                    // public function: can be called from ECMA wrapper of ECMA shell:
                    RLinetypePattern* self = 
                        getSelf("getPatternLength", context);
                  

                //Q_ASSERT(self!=NULL);
                if (self==NULL) {
                    return REcmaHelper::throwError("self is NULL", context);
                }
                
    
    if( context->argumentCount() ==
    0
    ){
    // prepare arguments:
    
    // end of arguments

    // call C++ function:
    // return type 'double'
    double cppResult =
        
               self->getPatternLength();
        // return type: double
                // standard Type
                result = QScriptValue(cppResult);
            
    } else


        
            {
               return REcmaHelper::throwError("Wrong number/types of arguments for RLinetypePattern.getPatternLength().",
                   context);
            }
            //REcmaHelper::functionEnd("REcmaLinetypePattern::getPatternLength", context, engine);
            return result;
        }
Exemple #2
0
double RExporter::getPatternOffset(double length,
        const RLinetypePattern& pattern, int index, double* gap) {
    double patternLength = pattern.getPatternLength();
    if (patternLength<RS::PointTolerance) {
        return 0.0;
    }

    double po = fabs(pattern.getDashLengthAt(index)) / 2;
    for (int i = index - 1; i >= 0; --i) {
        po += fabs(pattern.getDashLengthAt(i));
    }
    double offset = length / 2 - po;
    int m = (int) RMath::trunc(offset / patternLength);
    offset -= (m + 1) * patternLength;
    if (gap != NULL) {
        *gap = pattern.getDelta(-offset);
    }
    return offset;
}
Exemple #3
0
void RExporter::exportArc(const RArc& arc, double offset) {
    if (!arc.isValid()) {
        return;
    }

    RLinetypePattern p = getLinetypePattern();

    if (getEntity() == NULL || !p.isValid() || p.getNumDashes() == 1 || draftMode || screenBasedLinetypes) {
        exportArcSegment(arc);
        return;
    }

    RArc normalArc = arc;
    if (arc.isReversed()) {
        normalArc.reverse();
    }

    if (normalArc.radius < 1.0e-12) {
        return;
    }

    p.scale(getPatternFactor());

    double length = normalArc.getLength();
    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) {
        exportArcSegment(arc);
        return;
    }

    double* vp = NULL;
    vp = new double[p.getNumDashes()];
    for (int i = 0; i < p.getNumDashes(); ++i) {
        vp[i] = fabs(p.getDashLengthAt(i)) / normalArc.radius;
    }

    if (RMath::isNaN(offset)) {
        offset = getPatternOffset(length, p);
    }

    QList<RArc> arcSegments;
    bool done = false;
    int i = 0;
    double cursor = normalArc.getStartAngle() + offset / normalArc.radius;
    double total = offset;
    bool dashFound = false;
    bool gapFound = false;
    double a1 = normalArc.getStartAngle();
    double a2;
    do {
        if (dashFound && !gapFound) {
            if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) {
                arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, normalArc.getEndAngle()));
                break;
            }
            arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, a2));
        }
        if (p.getDashLengthAt(i) > 0) {
            // dash, no gap
            if (total + p.getDashLengthAt(i) > 0) {
                a1 = cursor;
                if (total < 0 || !dashFound) {
                    a1 = normalArc.startAngle;
                }
                a2 = cursor + vp[i];
                if (fabs(a2 - normalArc.getStartAngle()) > 1.0e-6) {
                    dashFound = true;
                }
            }
            gapFound = false;
        } 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) {
            arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, normalArc.getEndAngle()));
        } else {
            arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, a2));
        }
    }

    if (arc.isReversed()) {
        for (int i=arcSegments.length()-1; i>=0; i--) {
            arcSegments[i].reverse();
            exportArcSegment(arcSegments[i]);
        }
    }
    else {
        for (int i=0; i<arcSegments.length(); i++) {
            exportArcSegment(arcSegments[i]);
        }
    }

    delete[] vp;
}
Exemple #4
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;
}
Exemple #5
0
void RExporter::exportArc(const RArc& arc, double offset) {
    if (!arc.isValid()) {
        return;
    }

    if (getEntity() == NULL || draftMode || screenBasedLinetypes || twoColorSelectedMode) {
        exportArcSegment(arc);
        return;
    }

    RLinetypePattern p = getLinetypePattern();
    if (!p.isValid() || p.getNumDashes() <= 1) {
        exportArcSegment(arc);
        return;
    }

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

    RArc normalArc = arc;
    if (arc.isReversed()) {
        normalArc.reverse();
    }

    if (normalArc.radius < 1.0e-12) {
        return;
    }

    RArcExporter(*this, arc, offset);

    /*
    p.scale(getLineTypePatternScale(p));

    double length = normalArc.getLength();
    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) {
        exportArcSegment(arc);
        return;
    }

    double* vp = NULL;
    vp = new double[p.getNumDashes()];
    for (int i = 0; i < p.getNumDashes(); ++i) {
        vp[i] = fabs(p.getDashLengthAt(i)) / normalArc.radius;
    }

    //bool optimizeEnds = false;
    if (RMath::isNaN(offset)) {
        offset = p.getPatternOffset(length);
        //optimizeEnds = true;
    }

    QList<RArc> arcSegments;
    bool done = false;
    int i = 0;
    double cursor = normalArc.getStartAngle() + offset / normalArc.radius;
    double total = offset;
    bool dashFound = false;
    bool gapFound = false;
    double a1 = normalArc.getStartAngle();
    double a2 = 0.0;
    do {
        if (dashFound && !gapFound) {
            if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) {
                arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, normalArc.getEndAngle()));
                break;
            }
            arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, a2));
        }
        if (p.getDashLengthAt(i) >= 0.0) {
            // dash, no gap
            if (total + p.getDashLengthAt(i) >= 0.0) {
                a1 = cursor;
                if (total < 0.0 || !dashFound) {
                    a1 = normalArc.startAngle;
                }
                a2 = cursor + vp[i];
                if (fabs(a2 - normalArc.getStartAngle()) > 1.0e-6) {
                    dashFound = true;
                }
            }
            gapFound = false;
        } else {
            gapFound = true;
        }
        cursor += vp[i];
        total += fabs(p.getDashLengthAt(i));
        done = total > length;

        if (!done && total>0.0) {
            // handle shape at end of dash / gap:
            if (p.hasShapeAt(i)) {
                QList<RPainterPath> pps = p.getShapeAt(i);
//                RVector min = RPainterPath::getMinList(pps);
//                RVector max = RPainterPath::getMaxList(pps);
                RPainterPath::rotateList(pps, cursor+M_PI/2);
                RPainterPath::translateList(pps, normalArc.getPointAtAngle(cursor));
                exportPainterPaths(pps);
            }
        }

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

    if (!gapFound || !dashFound) {
        if (total + fabs(p.getDashLengthAt(i)) >= length - 1.0e-6) {
            arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, normalArc.getEndAngle()));
        } else {
            arcSegments.append(RArc(normalArc.getCenter(), normalArc.getRadius(), a1, a2));
        }
    }

    if (arc.isReversed()) {
        for (int i=arcSegments.length()-1; i>=0; i--) {
            arcSegments[i].reverse();
            exportArcSegment(arcSegments[i], true);
        }
    }
    else {
        for (int i=0; i<arcSegments.length(); i++) {
            exportArcSegment(arcSegments[i], true);
        }
    }

    delete[] vp;
    */
}
Exemple #6
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 #7
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();
        }
    }
    */
}