/** * 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; }
/** * 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; }