Logo Search packages:      
Sourcecode: qcad version File versions  Download package

void RS_Hatch::update (  )  [virtual]

Updates the Hatch. Called when the hatch or it's data, position, alignment, .. changes.

Reimplemented from RS_EntityContainer.

Definition at line 127 of file rs_hatch.cpp.

References activateContour(), RS_EntityContainer::addEntity(), RS_HatchData::angle, RS_Vector::angleTo(), calculateBorders(), RS_EntityContainer::calculateBorders(), RS_EntityContainer::clone(), RS_Vector::distanceTo(), RS2::EntityArc, RS2::EntityCircle, RS2::EntityLine, RS_EntityContainer::firstEntity(), RS2::FlagInvalid, RS2::FlagTemp, RS_VectorSolutions::get(), RS_Circle::getCenter(), RS_Arc::getCenter(), RS_Arc::getEndpoint(), RS_Line::getEndpoint(), RS_Information::getIntersection(), RS_Arc::getLength(), RS_Line::getLength(), RS_Entity::getMax(), RS_Arc::getMiddlepoint(), RS_Line::getMiddlepoint(), RS_Entity::getMin(), RS_Arc::getNearestDist(), RS_Line::getNearestDist(), RS_Circle::getRadius(), RS_Entity::getSize(), RS_Arc::getStartpoint(), RS_Line::getStartpoint(), RS_Information::isPointInsideContour(), RS_Arc::isReversed(), RS_Undoable::isUndone(), RS_Entity::move(), RS_EntityContainer::nextEntity(), RS_HatchData::pattern, RS_EntityContainer::removeEntity(), RS_Entity::reparent(), RS_Entity::rotate(), rotate(), RS_EntityContainer::RS_EntityContainer(), RS_HatchData::scale, RS_EntityContainer::scale(), RS_Flags::setFlag(), RS_Entity::setLayer(), RS_Entity::setPen(), RS_Vector::setPolar(), RS_HatchData::solid, RS_Entity::updateEnabled, RS_Vector::valid, validate(), RS_Vector::x, and RS_Vector::y.

Referenced by RS_FilterDXF::endEntity(), mirror(), move(), rotate(), scale(), stretch(), and RS_ActionDrawHatch::trigger().

                      {
    //std::cout << "RS_Hatch::update\n";

#if QT_VERSION>=0x030000
    if (updateRunning) {
        return;
    }

    if (updateEnabled==false) {
        return;
    }

    if (data.solid==true) {
        return;
    }

    RS_DEBUG->print("RS_Hatch::update");
    updateRunning = true;

    // delete old hatch:
    if (hatch!=NULL) {
        removeEntity(hatch);
        hatch = NULL;
    }

    if (isUndone()) {
        updateRunning = false;
        return;
    }

      if (!validate()) {
            RS_DEBUG->print("RS_Hatch::update: invalid contour");
            std::cerr << "Warning: invalid contour in hatch found" << std::endl;
        updateRunning = false;
            return;
      }

    // search pattern:
    RS_DEBUG->print("RS_Hatch::update: requesting pattern");
    RS_Pattern* pat = RS_PATTERNLIST->requestPattern(data.pattern);
    if (pat==NULL) {
        updateRunning = false;
        RS_DEBUG->print("RS_Hatch::update: requesting pattern: not found");
        return;
    }
    RS_DEBUG->print("RS_Hatch::update: requesting pattern: OK");

    //std::cout << "RS_Hatch::update 001\n";

    // reactivate contour:
    //std::cout << "RS_Hatch::update: reactivate contour\n";
    activateContour(true);

    // load or get pattern:
    //std::cout << "loading pattern: " << data.pattern.latin1() << "\n";


    RS_DEBUG->print("RS_Hatch::update: cloning pattern");
    pat = (RS_Pattern*)pat->clone();
    RS_DEBUG->print("RS_Hatch::update: cloning pattern: OK");

    // scale pattern
    RS_DEBUG->print("RS_Hatch::update: scaling pattern");
    pat->scale(RS_Vector(0.0,0.0), RS_Vector(data.scale, data.scale));
    pat->calculateBorders();
    activateContour(true);
    calculateBorders();
    RS_DEBUG->print("RS_Hatch::update: scaling pattern: OK");

    //std::cout << "RS_Hatch::update 002\n";

    // find out how many pattern-instances we need in x/y:
    int px1, py1, px2, py2;
    double f;
    RS_Hatch* copy = (RS_Hatch*)this->clone();
    copy->rotate(RS_Vector(0.0,0.0), -data.angle);
    copy->calculateBorders();

    // create a pattern over the whole contour.
    RS_Vector pSize = pat->getSize();
    RS_Vector cPos = getMin();
    RS_Vector cSize = getSize();


    RS_DEBUG->print("RS_Hatch::update: pattern size: %f/%f", pSize.x, pSize.y);
    RS_DEBUG->print("RS_Hatch::update: contour size: %f/%f", cSize.x, cSize.y);

    if (cSize.x<1.0e-6 || cSize.y<1.0e-6 ||
            pSize.x<1.0e-6 || pSize.y<1.0e-6 ||
            cSize.x>RS_MAXDOUBLE-1 || cSize.y>RS_MAXDOUBLE-1 ||
            pSize.x>RS_MAXDOUBLE-1 || pSize.y>RS_MAXDOUBLE-1) {
        delete pat;
        delete copy;
        updateRunning = false;
        RS_DEBUG->print("RS_Hatch::update: contour size or pattern size too small");
        return;
    }

    // avoid huge memory consumption:
    else if (cSize.x/pSize.x>100 || cSize.y/pSize.y>100) {
        RS_DEBUG->print("RS_Hatch::update: contour size too large or pattern size too small");
        return;
    }

    //std::cout << "RS_Hatch::update 003\n";

    f = copy->getMin().x/pat->getSize().x;
    px1 = (int)floor(f);
    f = copy->getMin().y/pat->getSize().y;
    py1 = (int)floor(f);
    f = copy->getMax().x/pat->getSize().x;
    px2 = (int)ceil(f) - 1;
    f = copy->getMax().y/pat->getSize().y;
    py2 = (int)ceil(f) - 1;

    RS_EntityContainer tmp;   // container for untrimmed lines

    // adding array of patterns to tmp:
    RS_DEBUG->print("RS_Hatch::update: creating pattern carpet");

    for (int px=px1; px<=px2; px++) {

        //std::cout << "px: " << px << "\n";

        for (int py=py1; py<=py2; py++) {

            //std::cout << "py: " << py << "\n";

            for (RS_Entity* e=pat->firstEntity(); e!=NULL;
                    e=pat->nextEntity()) {

                //std::cout << "adding entity for pattern..\n";

                RS_Entity* te = e->clone();
                //te->move(cPos + RS_Vector(px*pSize.x,py*pSize.y));
                te->rotate(RS_Vector(0.0,0.0), data.angle);
                RS_Vector v1, v2;
                v1.setPolar(px*pSize.x, data.angle);
                v2.setPolar(py*pSize.y, data.angle+M_PI/2.0);
                te->move(v1+v2);
                tmp.addEntity(te);
            }
        }
    }

    //std::cout << "RS_Hatch::update 004\n";

    delete pat;
    pat = NULL;
    RS_DEBUG->print("RS_Hatch::update: creating pattern carpet: OK");


    RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet");
    // cut pattern to contour shape:
    RS_EntityContainer tmp2;   // container for small cut lines
    RS_Line* line = NULL;
    RS_Arc* arc = NULL;
    RS_Circle* circle = NULL;
    for (RS_Entity* e=tmp.firstEntity(); e!=NULL;
            e=tmp.nextEntity()) {

        RS_Vector startPoint;
        RS_Vector endPoint;
        RS_Vector center = RS_Vector(false);
        bool reversed;

        if (e->rtti()==RS2::EntityLine) {
            line = (RS_Line*)e;
            arc = NULL;
            circle = NULL;
            startPoint = line->getStartpoint();
            endPoint = line->getEndpoint();
            center = RS_Vector(false);
            reversed = false;
        } else if (e->rtti()==RS2::EntityArc) {
            arc = (RS_Arc*)e;
            line = NULL;
            circle = NULL;
            startPoint = arc->getStartpoint();
            endPoint = arc->getEndpoint();
            center = arc->getCenter();
            reversed = arc->isReversed();
        } else if (e->rtti()==RS2::EntityCircle) {
            circle = (RS_Circle*)e;
            line = NULL;
            arc = NULL;
            startPoint = circle->getCenter()
                         + RS_Vector(circle->getRadius(), 0.0);
            endPoint = startPoint;
            center = circle->getCenter();
            reversed = false;
        } else {
            continue;
        }

        // getting all intersections of this pattern line with the contour:
        RS_PtrList<RS_Vector> is;
        is.setAutoDelete(true);
        is.append(new RS_Vector(startPoint));

        for (RS_Entity* loop=firstEntity(); loop!=NULL;
                loop=nextEntity()) {

            //std::cout << "  loop:\n";
            //std::cout << "  001\n";

            if (loop->isContainer()) {
                //std::cout << "  002\n";
                for (RS_Entity* p=((RS_EntityContainer*)loop)->firstEntity();
                        p!=NULL;
                        p=((RS_EntityContainer*)loop)->nextEntity()) {

                    //std::cout << "    get inters:\n";

                    RS_VectorSolutions sol =
                        RS_Information::getIntersection(e, p, true);

                    //std::cout << "    get inters ok\n";


                    for (int i=0; i<=1; ++i) {
                        if (sol.get(i).valid) {
                            is.append(new RS_Vector(sol.get(i)));
                            RS_DEBUG->print("  pattern line intersection: %f/%f",
                                            sol.get(i).x, sol.get(i).y);
                            //std::cout << "  pattern intersection: "
                            //<< sol.get(i) << "\n";
                        }
                    }
                }
            }
            //std::cout << "  loop ok\n";
        }

        //std::cout << "  add intersection:\n";


        is.append(new RS_Vector(endPoint));

        //std::cout << "  sort intersections\n";

        // sort the intersection points into is2:
        RS_Vector sp = startPoint;
        double sa = center.angleTo(sp);
        RS_PtrList<RS_Vector> is2;
        is2.setAutoDelete(true);
        bool done;
        double minDist;
        double dist = 0.0;
        //int idx = -1;
        RS_Vector* av;
        RS_Vector last = RS_Vector(false);
        do {
            done = true;
            minDist = RS_MAXDOUBLE;
            av = NULL;
            for (RS_Vector* v = is.first(); v!=NULL; v = is.next()) {
                if (line!=NULL) {
                    dist = sp.distanceTo(*v);
                } else if (arc!=NULL || circle!=NULL) {
                    double a = center.angleTo(*v);
                    if (reversed) {
                        if (a>sa) {
                            a-=2*M_PI;
                        }
                        dist = sa-a;
                    } else {
                        if (a<sa) {
                            a+=2*M_PI;
                        }
                        dist = a-sa;
                    }
                    //std::cout << "dist: " << dist << "\n";
                    if (fabs(dist-2*M_PI)<1.0e-6) {
                        dist = 0.0;
                    }
                    //std::cout << "  dist: " << dist << "\n";
                }
                if (dist<minDist) {
                    minDist = dist;
                    done = false;
                    av = v;
                    //idx = is.at();
                }
            }

            // copy to sorted list, removing double points


            if (!done && av!=NULL) {
                if (last.valid==false || last.distanceTo(*av)>1.0e-10) {
                    is2.append(new RS_Vector(*av));
                    last = *av;
                }
                //std::cout << "vector: " << *av << "\n";
                is.remove(av);
                av = NULL;
            }
        } while(!done);

        // add small cut lines / arcs to tmp2:
        for (RS_Vector* v1 = is2.first(); v1!=NULL;) {
            RS_Vector* v2 = is2.next();

            if (v1!=NULL && v2!=NULL) {
                if (line!=NULL) {
                    tmp2.addEntity(new RS_Line(&tmp2,
                                               RS_LineData(*v1, *v2)));
                } else if (arc!=NULL || circle!=NULL) {
                    tmp2.addEntity(new RS_Arc(&tmp2,
                                              RS_ArcData(center,
                                                         center.distanceTo(*v1),
                                                         center.angleTo(*v1),
                                                         center.angleTo(*v2),
                                                         reversed)));
                }

                //std::cout << "adding small line: "
               //               << *v1 << " " << *v2 << "\n";
            }

            v1 = v2;
        }
    }

    //std::cout << "RS_Hatch::update 005\n";


    // updating hatch / adding entities that are inside
    RS_DEBUG->print("RS_Hatch::update: cutting pattern carpet: OK");

    //RS_EntityContainer* rubbish = new RS_EntityContainer(getGraphic());

    // the hatch pattern entities:
    hatch = new RS_EntityContainer(this);
    hatch->setPen(RS_Pen(RS2::FlagInvalid));
    hatch->setLayer(NULL);
    hatch->setFlag(RS2::FlagTemp);

    //calculateBorders();

    for (RS_Entity* e=tmp2.firstEntity(); e!=NULL;
            e=tmp2.nextEntity()) {

        RS_Vector middlePoint;
        RS_Vector middlePoint2;
        if (e->rtti()==RS2::EntityLine) {
            RS_Line* line = (RS_Line*)e;
            middlePoint = line->getMiddlepoint();
            middlePoint2 = line->getNearestDist(line->getLength()/2.1,
                                                line->getStartpoint());
        } else if (e->rtti()==RS2::EntityArc) {
            RS_Arc* arc = (RS_Arc*)e;
            middlePoint = arc->getMiddlepoint();
            middlePoint2 = arc->getNearestDist(arc->getLength()/2.1,
                                               arc->getStartpoint());
        } else {
            middlePoint = RS_Vector(false);
            middlePoint2 = RS_Vector(false);
        }

        if (middlePoint.valid) {
            bool onContour=false;

            //if (middlePoint.x < getMin().x || middlePoint.x > getMax().x ||
            //    middlePoint.y < getMin().y || middlePoint.y > getMax().y) {
            //    break;
            //}

            if (RS_Information::isPointInsideContour(
                        middlePoint,
                        this, &onContour) ||
                    RS_Information::isPointInsideContour(middlePoint2, this)) {

                //if (!onContour || RS_Information::isPointInsideContour(
                //            middlePoint2, this)) {

                RS_Entity* te = e->clone();
                te->setPen(RS_Pen(RS2::FlagInvalid));
                te->setLayer(NULL);
                te->reparent(hatch);
                hatch->addEntity(te);
                //}
            }
        }
    }

    //std::cout << "RS_Hatch::update 006\n";



    addEntity(hatch);
    //getGraphic()->addEntity(rubbish);

    calculateBorders();

    // deactivate contour:
    activateContour(false);

    updateRunning = false;

    RS_DEBUG->print("RS_Hatch::update: OK");

    //std::cout << "RS_Hatch::update: OK\n";
#endif

}


Generated by  Doxygen 1.6.0   Back to index