/**
 * Rearranges the atomic entities in this container in a way that connected
 * entities are stored in the right order and direction.
 * Non-recoursive. Only affects atomic entities in this container.
 *
 * @retval true all contours were closed
 * @retval false at least one contour is not closed
 */
bool RS_ActionPolylineSegment::convertPolyline(RS_Entity* selectedEntity) {

        RS_DEBUG->print("RS_ActionPolylineSegment::convertPolyline");

        RS_Vector current(false);
        RS_Vector start(false);
        RS_Vector end(false);
        RS_EntityContainer tmp;

        bool closed = true;

        int pos = container->findEntity(selectedEntity);
        RS_Entity* e1=container->entityAt(pos);
        if (!e1) return false;

        if (document!=NULL) {
                document->startUndoCycle();
        }
        if (document!=NULL) {
                if (e1!=NULL && e1->isEdge() && !e1->isContainer() &&
                                        !e1->isProcessed()) {

                        RS_AtomicEntity* ce = (RS_AtomicEntity*)e1;

///////////////////////////////////////////////////
                        ce->setUndoState(true);
                        document->addUndoable(ce);
///////////////////////////////////////////////////

                        // next contour start:
                        ce->setProcessed(true);
                        tmp.addEntity(ce->clone());
                        current = ce->getStartpoint();
                        end = ce->getEndpoint();

                        // find first connected entities:
                        for (int ei=pos-1; ei>=0; --ei) {
                                RS_Entity* e2=container->entityAt(ei);

                                if (e2!=NULL && e2->isEdge() && !e2->isContainer() &&
                                                !e2->isProcessed()) {

                                        RS_AtomicEntity* e = (RS_AtomicEntity*)e2;
///////////////////////////////////////////////////
                                        e->setUndoState(true);
                                        document->addUndoable(e);
///////////////////////////////////////////////////
                                        if (e->getEndpoint().distanceTo(current) <
                                                        1.0e-4) {
                                                e->setProcessed(true);
                                                tmp.insertEntity(0,e->clone());
                                                current = e->getStartpoint();
                                        } else if (e->getStartpoint().distanceTo(current) <
                                                           1.0e-4) {
                                                e->setProcessed(true);
                                                RS_AtomicEntity* cl = (RS_AtomicEntity*)e->clone();
                                                cl->reverse();
                                                tmp.insertEntity(0,cl);
                                                current = cl->getStartpoint();
                                        }else
                                                break;
                                }
                        }

                        if (current.distanceTo(end)>1.0e-4) {
                                closed = false;
                        }

                        current = ce->getEndpoint();
                        start = ce->getStartpoint();
                        // find last connected entities:
                        for (uint ei=pos+1; ei<container->count(); ++ei) {
                                RS_Entity* e2=container->entityAt(ei);
///////////////////////////////////////////////////
                                e2->setUndoState(true);
                                document->addUndoable(e2);
///////////////////////////////////////////////////
                                if (e2!=NULL && e2->isEdge() && !e2->isContainer() &&
                                                !e2->isProcessed()) {
                                        RS_AtomicEntity* e = (RS_AtomicEntity*)e2;
                                        if (e->getStartpoint().distanceTo(current) <
                                                        1.0e-4) {
                                                e->setProcessed(true);
                                                tmp.addEntity(e->clone());
                                                current = e->getEndpoint();
                                        } else if (e->getEndpoint().distanceTo(current) <
                                                           1.0e-4) {
                                                e->setProcessed(true);
                                                RS_AtomicEntity* cl = (RS_AtomicEntity*)e->clone();
                                                cl->reverse();
                                                tmp.addEntity(cl);
                                                current = cl->getEndpoint();
                                        }else
                                                break;
                                }
                        }
                        if (current.distanceTo(start)>1.0e-4) {
                                closed = false;
                        }
                }
        }
        if (document!=NULL) {
                document->endUndoCycle();
        }

        RS_Polyline* newPolyline = new RS_Polyline(container, RS_PolylineData(RS_Vector(false), RS_Vector(false), closed));
        newPolyline->setLayerToActive();
        newPolyline->setPenToActive();
        // add new polyline:
        bool first = true;
        RS_Entity* lastEntity = tmp.lastEntity();
        for (RS_Entity* en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity()) {
                en->setProcessed(false);
                double bulge = 0.0;
                if (en->rtti()==RS2::EntityArc) {
                        bulge = ((RS_Arc*)en)->getBulge();
                } else {
                        bulge = 0.0;
                }
                if (first) {
                        newPolyline->setNextBulge(bulge);
                        newPolyline->addVertex(((RS_AtomicEntity*)en)->getStartpoint());
                        first = false;
                }
                if (en!=lastEntity || closed==false){
                        newPolyline->setNextBulge(bulge);
                        newPolyline->addVertex(((RS_AtomicEntity*)en)->getEndpoint());
                }
        }
        double bulge = lastEntity->rtti() == RS2::EntityArc? ((RS_Arc*)lastEntity)->getBulge():0.0;
        newPolyline->setNextBulge(bulge);
        newPolyline->endPolyline();
        container->addEntity(newPolyline);

        if (graphicView!=NULL) {
                graphicView->drawEntity(newPolyline);
        }

        if (document!=NULL) {
                document->startUndoCycle();
                document->addUndoable(newPolyline);
                document->endUndoCycle();
        }
        RS_DEBUG->print("RS_ActionPolylineSegment::convertPolyline: OK");
        return closed;
}
Пример #2
0
/**
 * Rearranges the atomic entities in this container in a way that connected
 * entities are stored in the right order and direction.
 * Non-recoursive. Only affects atomic entities in this container.
 * 
 * @retval true all contours were closed
 * @retval false at least one contour is not closed
 */
bool RS_EntityContainer::optimizeContours() {

    RS_DEBUG->print("RS_EntityContainer::optimizeContours");

    RS_Vector current(false);
    RS_Vector start(false);
    RS_EntityContainer tmp;

    bool changed = false;
    bool closed = true;

    for (uint ci=0; ci<count(); ++ci) {
        RS_Entity* e1=entityAt(ci);

        if (e1!=NULL && e1->isEdge() && !e1->isContainer() &&
                !e1->isProcessed()) {

            RS_AtomicEntity* ce = (RS_AtomicEntity*)e1;

            // next contour start:
            ce->setProcessed(true);
            tmp.addEntity(ce->clone());
            current = ce->getEndpoint();
            start = ce->getStartpoint();

            // find all connected entities:
            bool done;
            do {
                done = true;
                for (uint ei=0; ei<count(); ++ei) {
                    RS_Entity* e2=entityAt(ei);

                    if (e2!=NULL && e2->isEdge() && !e2->isContainer() &&
                            !e2->isProcessed()) {

                        RS_AtomicEntity* e = (RS_AtomicEntity*)e2;

                        if (e->getStartpoint().distanceTo(current) <
                                1.0e-4) {

                            e->setProcessed(true);
                            tmp.addEntity(e->clone());
                            current = e->getEndpoint();

                            done=false;
                        } else if (e->getEndpoint().distanceTo(current) <
                                   1.0e-4) {

                            e->setProcessed(true);
                            RS_AtomicEntity* cl = (RS_AtomicEntity*)e->clone();
                            cl->reverse();
                            tmp.addEntity(cl);
                            current = cl->getEndpoint();

                            changed = true;
                            done=false;
                        }
                    }
                }
                if (!done) {
                    changed = true;
                }
            } while (!done);

            if (current.distanceTo(start)>1.0e-4) {
                closed = false;
            }
        }
    }

    // remove all atomic entities:
    bool done;
    do {
        done = true;
        for (RS_Entity* en=firstEntity(); en!=NULL; en=nextEntity()) {
            if (!en->isContainer()) {
                removeEntity(en);
                done = false;
                break;
            }
        }
    } while (!done);

    // add new sorted entities:
    for (RS_Entity* en=tmp.firstEntity(); en!=NULL; en=tmp.nextEntity()) {
        en->setProcessed(false);
        addEntity(en->clone());
    }

    RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
    return closed;
}