/**
 * Constructor.
 */
RS_ActionPARISDebugCreateContainer::RS_ActionPARISDebugCreateContainer(
    RS_EntityContainer& container,
    RS_GraphicView& graphicView)
        : RS_ActionInterface("rs_actionparischeckcont",
                     container, graphicView) {

    //QMessageBox::about(NULL, "info", "check container");
    RS_Document* theDoc = (RS_Document*) &container;

    if (theDoc->countSelected() < 2) {
        return;
	}

    RS_EntityContainer* con = new RS_EntityContainer(theDoc, true);
    RS_PtrListIterator<RS_Entity> it = theDoc->createIterator();
    RS_Entity* e;

    while ( (e = it.current()) != 0) {
        ++it;
        if (e->isSelected()) {
            con->addEntity(e);
            e->setParent(con);
        }
    }

    theDoc -> addEntity(con);
}
Example #2
0
void QG_GraphicView::layerActivated(RS_Layer *layer) {
	RS_SETTINGS->beginGroup("/Modify");
	bool toActivated= (RS_SETTINGS->readNumEntry("/ModifyEntitiesToActiveLayer", 0)==1);
	RS_SETTINGS->endGroup();

	if(!toActivated) return;
    RS_EntityContainer *container = this->getContainer();
    RS_Graphic* graphic = this->getGraphic();
    QList<RS_Entity*> clones;

    if (graphic) {
        graphic->startUndoCycle();
    }

    for (auto en: *container) {
        if (!en) continue;
        if (!en->isSelected()) continue;

        RS_Entity* cl = en->clone();
        cl->setLayer(layer);
        this->deleteEntity(en);
        en->setSelected(false);
        cl->setSelected(false);
        clones << cl;

        if (!graphic) continue;

        en->setUndoState(true);
        graphic->addUndoable(en);
    }

    for (auto cl: clones) {
        container->addEntity(cl);
        this->drawEntity(cl);

        if (!graphic) continue;

        graphic->addUndoable(cl);
    }

    if (graphic) {
        graphic->endUndoCycle();
        graphic->updateInserts();
    }

    container->calculateBorders();
    container->setSelected(false);
    redraw(RS2::RedrawDrawing);
}
Example #3
0
/**
 * Updates the Hatch. Called when the
 * hatch or it's data, position, alignment, .. changes.
 */
void RS_Hatch::update() {
        RS_DEBUG->print("RS_Hatch::update");
        RS_DEBUG->print("RS_Hatch::update: contour has %d loops", count());

    updateError = HATCH_OK;
    if (updateRunning) {
        return;
    }

    if (updateEnabled==false) {
        return;
    }

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

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

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

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

    if (!validate()) {
        RS_DEBUG->print(RS_Debug::D_WARNING,
                        "RS_Hatch::update: invalid contour in hatch found");
        updateRunning = false;
        updateError = HATCH_INVALID_CONTOUR;
        return;
    }

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

    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();
    forcedCalculateBorders();
    RS_DEBUG->print("RS_Hatch::update: scaling pattern: OK");

    // 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->forcedCalculateBorders();

    // create a pattern over the whole contour.
    RS_Vector pSize = pat->getSize();
    RS_Vector rot_center=pat->getMin();
//    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");
        updateError = HATCH_TOO_SMALL;
        return;
    }

    // avoid huge memory consumption:
    else if ( cSize.x* cSize.y/(pSize.x*pSize.y)>1e4) {
        RS_DEBUG->print("RS_Hatch::update: contour size too large or pattern size too small");
        delete pat;
        delete copy;
        updateError = HATCH_AREA_TOO_BIG;
        return;
    }

    f = copy->getMin().x/pSize.x;
    px1 = (int)floor(f);
    f = copy->getMin().y/pSize.y;
    py1 = (int)floor(f);
    f = copy->getMax().x/pSize.x;
    px2 = (int)ceil(f);
    f = copy->getMax().y/pSize.y;
    py2 = (int)ceil(f);
    RS_Vector dvx=RS_Vector(data.angle)*pSize.x;
    RS_Vector dvy=RS_Vector(data.angle+M_PI*0.5)*pSize.y;
    pat->rotate(rot_center, data.angle);
    pat->move(-rot_center);


    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++) {
		for (int py=py1; py<py2; py++) {
			for(auto e: *pat){
                RS_Entity* te=e->clone();
                te->move(dvx*px + dvy*py);
                tmp.addEntity(te);
            }
        }
    }

    delete pat;
    pat = nullptr;
    delete copy;
    copy = nullptr;
    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 = nullptr;
	RS_Arc* arc = nullptr;
	RS_Circle* circle = nullptr;
	RS_Ellipse* ellipse = nullptr;
	for(auto e: tmp){

		line = nullptr;
		arc = nullptr;
		circle = nullptr;
		ellipse = nullptr;

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

        switch(e->rtti()){
        case RS2::EntityLine:
            line=static_cast<RS_Line*>(e);
            startPoint = line->getStartpoint();
            endPoint = line->getEndpoint();
            break;
        case RS2::EntityArc:
            arc=static_cast<RS_Arc*>(e);
            startPoint = arc->getStartpoint();
            endPoint = arc->getEndpoint();
            center = arc->getCenter();
            reversed = arc->isReversed();
            break;
        case RS2::EntityCircle:
            circle=static_cast<RS_Circle*>(e);
            startPoint = circle->getCenter()
                    + RS_Vector(circle->getRadius(), 0.0);
            endPoint = startPoint;
            center = circle->getCenter();
            break;
        case RS2::EntityEllipse:
            ellipse = static_cast<RS_Ellipse*>(e);
            startPoint = ellipse->getStartpoint();
            endPoint = ellipse->getEndpoint();
            center = ellipse->getCenter();
            reversed = ellipse->isReversed();
            break;
        default:
            continue;
        }

        // getting all intersections of this pattern line with the contour:
        QList<std::shared_ptr<RS_Vector> > is;

		for(auto loop: entities){

            if (loop->isContainer()) {
				for(auto p: * static_cast<RS_EntityContainer*>(loop)){

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

					for (const RS_Vector& vp: sol){
						if (vp.valid) {
							is.append(std::shared_ptr<RS_Vector>(
										  new RS_Vector(vp)
										  ));
							RS_DEBUG->print("  pattern line intersection: %f/%f",
											vp.x, vp.y);
						}
					}
				}
			}
		}


        QList<std::shared_ptr<RS_Vector> > is2;//to be filled with sorted intersections
        is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(startPoint)));

        // sort the intersection points into is2 (only if there are intersections):
        if(is.size() == 1)
        {//only one intersection
            is2.append(is.first());
        }
        else if(is.size() > 1)
        {
            RS_Vector sp = startPoint;
            double sa = center.angleTo(sp);
			if(ellipse ) sa=ellipse->getEllipseAngle(sp);
            bool done;
            double minDist;
            double dist = 0.0;
            std::shared_ptr<RS_Vector> av;
            std::shared_ptr<RS_Vector> v;
            RS_Vector last = RS_Vector(false);
            do {
                done = true;
                minDist = RS_MAXDOUBLE;
                av.reset();
                for (int i = 0; i < is.size(); ++i) {
                    v = is.at(i);
                    double a;
                    switch(e->rtti()){
                    case RS2::EntityLine:
                        dist = sp.distanceTo(*v);
                        break;
                    case RS2::EntityArc:
                    case RS2::EntityCircle:
                        a = center.angleTo(*v);
                        dist = reversed?
                                    fmod(sa - a + 2.*M_PI,2.*M_PI):
                                    fmod(a - sa + 2.*M_PI,2.*M_PI);
                        break;
                    case RS2::EntityEllipse:
                        a = ellipse->getEllipseAngle(*v);
                        dist = reversed?
                                    fmod(sa - a + 2.*M_PI,2.*M_PI):
                                    fmod(a - sa + 2.*M_PI,2.*M_PI);
                        break;
                    default:
                        break;

                    }

                    if (dist<minDist) {
                        minDist = dist;
                        done = false;
                        av = v;
                    }
                }

                // copy to sorted list, removing double points
                if (!done && av.get()) {
                    if (last.valid==false || last.distanceTo(*av)>RS_TOLERANCE) {
                        is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(*av)));
                        last = *av;
                    }
#if QT_VERSION < 0x040400
                    emu_qt44_removeOne(is, av);
#else
                    is.removeOne(av);
#endif

                    av.reset();
                }
            } while(!done);
        }

is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(endPoint)));

        // add small cut lines / arcs to tmp2:
            for (int i = 1; i < is2.size(); ++i) {
                auto v1 = is2.at(i-1);
                auto v2 = is2.at(i);


                if (line) {

					tmp2.addEntity(new RS_Line{&tmp2, *v1, *v2});
                } else if (arc || circle) {
                    if(fabs(center.angleTo(*v2)-center.angleTo(*v1)) > RS_TOLERANCE_ANGLE)
                    {//don't create an arc with a too small angle
                        tmp2.addEntity(new RS_Arc(&tmp2,
                                                  RS_ArcData(center,
                                                             center.distanceTo(*v1),
                                                             center.angleTo(*v1),
                                                             center.angleTo(*v2),
                                                             reversed)));
                    }

                }
            }

    }

    // 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(nullptr);
    hatch->setFlag(RS2::FlagTemp);

    //calculateBorders();

	for(auto e: tmp2){

        RS_Vector middlePoint;
        RS_Vector middlePoint2;
        if (e->rtti()==RS2::EntityLine) {
			RS_Line* line = static_cast<RS_Line*>(e);
            middlePoint = line->getMiddlePoint();
            middlePoint2 = line->getNearestDist(line->getLength()/2.1,
                                                line->getStartpoint());
        } else if (e->rtti()==RS2::EntityArc) {
			RS_Arc* arc = static_cast<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 (RS_Information::isPointInsideContour(
                        middlePoint,
                        this, &onContour) ||
                    RS_Information::isPointInsideContour(middlePoint2, this)) {

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

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

    forcedCalculateBorders();

    // deactivate contour:
    activateContour(false);

    updateRunning = false;

    RS_DEBUG->print("RS_Hatch::update: OK");
}
Example #4
0
void RS_ActionDrawHatch::trigger() {

    RS_DEBUG->print("RS_ActionDrawHatch::trigger()");

    //if (pos.valid) {
    //deletePreview();
	RS_Entity* e;

	// deselect unhatchable entities:
	for(auto e: *container){
        if (e->isSelected() && 
            (e->rtti()==RS2::EntityHatch ||
            /* e->rtti()==RS2::EntityEllipse ||*/ e->rtti()==RS2::EntityPoint ||
             e->rtti()==RS2::EntityMText || e->rtti()==RS2::EntityText ||
			 RS_Information::isDimension(e->rtti()))) {
			e->setSelected(false);
        }
    }
	for (e=container->firstEntity(RS2::ResolveAll); e;
            e=container->nextEntity(RS2::ResolveAll)) {
        if (e->isSelected() && 
            (e->rtti()==RS2::EntityHatch ||
            /* e->rtti()==RS2::EntityEllipse ||*/ e->rtti()==RS2::EntityPoint ||
             e->rtti()==RS2::EntityMText || e->rtti()==RS2::EntityText ||
			 RS_Information::isDimension(e->rtti()))) {
			e->setSelected(false);
        }
    }

	// look for selected contours:
    bool haveContour = false;
	for (e=container->firstEntity(RS2::ResolveAll); e;
            e=container->nextEntity(RS2::ResolveAll)) {
        if (e->isSelected()) {
            haveContour = true;
        }
    }

    if (!haveContour) {
        std::cerr << "no contour selected\n";
        return;
    }

    hatch = new RS_Hatch(container, data);
    hatch->setLayerToActive();
    hatch->setPenToActive();
    RS_EntityContainer* loop = new RS_EntityContainer(hatch);
    loop->setPen(RS_Pen(RS2::FlagInvalid));

    // add selected contour:
	for (RS_Entity* e=container->firstEntity(RS2::ResolveAll); e;
            e=container->nextEntity(RS2::ResolveAll)) {

        if (e->isSelected()) {
            e->setSelected(false);
			// entity is part of a complex entity (spline, polyline, ..):
			if (e->getParent() &&
// RVT - Don't de-delect the parent EntityPolyline, this is messing up the getFirst and getNext iterators
//			    (e->getParent()->rtti()==RS2::EntitySpline ||
//				 e->getParent()->rtti()==RS2::EntityPolyline)) {
                (e->getParent()->rtti()==RS2::EntitySpline)) {
                e->getParent()->setSelected(false);
            }
            RS_Entity* cp = e->clone();
            cp->setPen(RS_Pen(RS2::FlagInvalid));
            cp->reparent(loop);
            loop->addEntity(cp);
        }
    }

    hatch->addEntity(loop);
	if (hatch->validate()) {
		container->addEntity(hatch);

		if (document) {
			document->startUndoCycle();
			document->addUndoable(hatch);
			document->endUndoCycle();
		}
		hatch->update();

		graphicView->redraw(RS2::RedrawDrawing);

        bool printArea=true;
        switch( hatch->getUpdateError()) {
        case RS_Hatch::HATCH_OK :
            RS_DIALOGFACTORY->commandMessage(tr("Hatch created successfully."));
            break;
        case RS_Hatch::HATCH_INVALID_CONTOUR :
            RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Invalid contour found!"));
            printArea=false;
            break;
        case RS_Hatch::HATCH_PATTERN_NOT_FOUND :
            RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Pattern not found!"));
            break;
        case RS_Hatch::HATCH_TOO_SMALL :
            RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Contour or pattern too small!"));
            break;
        case RS_Hatch::HATCH_AREA_TOO_BIG :
            RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Contour too big!"));
            break;
        default :
            RS_DIALOGFACTORY->commandMessage(tr("Hatch Error: Undefined Error!"));
            printArea=false;
            break;
        }
        if(m_bShowArea&&printArea){
            RS_DIALOGFACTORY->commandMessage(tr("Total hatch area = %1").
                                             arg(hatch->getTotalArea(),10,'g',8));
        }

	}
	else {
		delete hatch;
		hatch = nullptr;
		RS_DIALOGFACTORY->commandMessage(tr("Invalid hatch area. Please check that "
		"the entities chosen form one or more closed contours."));
	}
    //}
}
/**
 * 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

 * to do: find closed contour by flood-fill
 */
bool RS_EntityContainer::optimizeContours() {
//    std::cout<<"RS_EntityContainer::optimizeContours: begin"<<std::endl;

//    DEBUG_HEADER
//    std::cout<<"loop with count()="<<count()<<std::endl;
    RS_DEBUG->print("RS_EntityContainer::optimizeContours");

    RS_EntityContainer tmp;
    tmp.setAutoUpdateBorders(false);
    bool closed=true;

    /** accept all full circles **/
    QList<RS_Entity*> enList;
	for(auto e1: entities){
        if (!e1->isEdge() || e1->isContainer() ) {
            enList<<e1;
            continue;
        }

        //detect circles and whole ellipses
        switch(e1->rtti()){
        case RS2::EntityEllipse:
			if(static_cast<RS_Ellipse*>(e1)->isEllipticArc())
                continue;
        case RS2::EntityCircle:
            //directly detect circles, bug#3443277
            tmp.addEntity(e1->clone());
            enList<<e1;
        default:
            continue;
        }

    }
    //    std::cout<<"RS_EntityContainer::optimizeContours: 1"<<std::endl;

    /** remove unsupported entities */
    for(RS_Entity* it: enList)
        removeEntity(it);

    /** check and form a closed contour **/
//    std::cout<<"RS_EntityContainer::optimizeContours: 2"<<std::endl;
    /** the first entity **/
	RS_Entity* current(nullptr);
    if(count()>0) {
        current=entityAt(0)->clone();
        tmp.addEntity(current);
        removeEntity(entityAt(0));
    }else {
        if(tmp.count()==0) return false;
    }
//    std::cout<<"RS_EntityContainer::optimizeContours: 3"<<std::endl;
    RS_Vector vpStart;
    RS_Vector vpEnd;
	if(current){
        vpStart=current->getStartpoint();
        vpEnd=current->getEndpoint();
    }
	RS_Entity* next(nullptr);
//    std::cout<<"RS_EntityContainer::optimizeContours: 4"<<std::endl;
    /** connect entities **/
    const QString errMsg=QObject::tr("Hatch failed due to a gap=%1 between (%2, %3) and (%4, %5)");

    while(count()>0){
        double dist(0.);
        RS_Vector&& vpTmp=getNearestEndpoint(vpEnd,&dist,&next);
        if(dist>1e-8) {
            if(vpEnd.squaredTo(vpStart)<1e-8){
                RS_Entity* e2=entityAt(0);
                tmp.addEntity(e2->clone());
                vpStart=e2->getStartpoint();
                vpEnd=e2->getEndpoint();
                removeEntity(e2);
                continue;
            }
            QG_DIALOGFACTORY->commandMessage(errMsg.arg(dist).arg(vpTmp.x).arg(vpTmp.y).arg(vpEnd.x).arg(vpEnd.y));
            closed=false;
        }
		if(next && closed){ 			//workaround if next is nullptr
            next->setProcessed(true);
            RS_Entity* eTmp = next->clone();
            if(vpEnd.squaredTo(eTmp->getStartpoint())>vpEnd.squaredTo(eTmp->getEndpoint()))
                eTmp->revertDirection();
            vpEnd=eTmp->getEndpoint();
            tmp.addEntity(eTmp);
        	removeEntity(next);
		} else { 			//workaround if next is nullptr
//      	    std::cout<<"RS_EntityContainer::optimizeContours: next is nullptr" <<std::endl;

			closed=false;	//workaround if next is nullptr
			break;			//workaround if next is nullptr
		} 					//workaround if next is nullptr
    }
//    DEBUG_HEADER
    if(vpEnd.valid && vpEnd.squaredTo(vpStart)>1e-8) {
        if(closed) QG_DIALOGFACTORY->commandMessage(errMsg.arg(vpEnd.distanceTo(vpStart))
                                         .arg(vpStart.x).arg(vpStart.y).arg(vpEnd.x).arg(vpEnd.y));
        closed=false;
    }
//    std::cout<<"RS_EntityContainer::optimizeContours: 5"<<std::endl;


    // add new sorted entities:
	for(auto en: tmp){
		en->setProcessed(false);
        addEntity(en->clone());
    }
//    std::cout<<"RS_EntityContainer::optimizeContours: 6"<<std::endl;

    RS_DEBUG->print("RS_EntityContainer::optimizeContours: OK");
//    std::cout<<"RS_EntityContainer::optimizeContours: end: count()="<<count()<<std::endl;
//    std::cout<<"RS_EntityContainer::optimizeContours: closed="<<closed<<std::endl;
    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_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;
}
void RS_ActionDrawHatch::trigger() {

    RS_DEBUG->print("RS_ActionDrawHatch::trigger()");

    //if (pos.valid) {
    //deletePreview();
	RS_Entity* e;

	// deselect unhatchable entities:
    for (e=container->firstEntity(RS2::ResolveNone); e!=NULL;
            e=container->nextEntity(RS2::ResolveNone)) {
        if (e->isSelected() && 
            (e->rtti()==RS2::EntityHatch ||
            /* e->rtti()==RS2::EntityEllipse ||*/ e->rtti()==RS2::EntityPoint ||
             e->rtti()==RS2::EntityMText || e->rtti()==RS2::EntityText ||
			 RS_Information::isDimension(e->rtti()))) {
			e->setSelected(false);
        }
    }
    for (e=container->firstEntity(RS2::ResolveAll); e!=NULL;
            e=container->nextEntity(RS2::ResolveAll)) {
        if (e->isSelected() && 
            (e->rtti()==RS2::EntityHatch ||
            /* e->rtti()==RS2::EntityEllipse ||*/ e->rtti()==RS2::EntityPoint ||
             e->rtti()==RS2::EntityMText || e->rtti()==RS2::EntityText ||
			 RS_Information::isDimension(e->rtti()))) {
			e->setSelected(false);
        }
    }

	// look for selected contours:
    bool haveContour = false;
    for (e=container->firstEntity(RS2::ResolveAll); e!=NULL;
            e=container->nextEntity(RS2::ResolveAll)) {
        if (e->isSelected()) {
            haveContour = true;
        }
    }

    if (!haveContour) {
        std::cerr << "no contour selected\n";
        return;
    }

    hatch = new RS_Hatch(container, data);
    hatch->setLayerToActive();
    hatch->setPenToActive();
    RS_EntityContainer* loop = new RS_EntityContainer(hatch);
    loop->setPen(RS_Pen(RS2::FlagInvalid));

    // add selected contour:
    for (RS_Entity* e=container->firstEntity(RS2::ResolveAll); e!=NULL;
            e=container->nextEntity(RS2::ResolveAll)) {

        if (e->isSelected()) {
            e->setSelected(false);
			// entity is part of a complex entity (spline, polyline, ..):
            if (e->getParent()!=NULL &&
// RVT - Don't de-delect the parent EntityPolyline, this is messing up the getFirst and getNext iterators
//			    (e->getParent()->rtti()==RS2::EntitySpline ||
//				 e->getParent()->rtti()==RS2::EntityPolyline)) {
                (e->getParent()->rtti()==RS2::EntitySpline)) {
                e->getParent()->setSelected(false);
            }
            RS_Entity* cp = e->clone();
            cp->setPen(RS_Pen(RS2::FlagInvalid));
            cp->reparent(loop);
            loop->addEntity(cp);
        }
    }

    hatch->addEntity(loop);
	if (hatch->validate()) {
		container->addEntity(hatch);

		if (document) {
			document->startUndoCycle();
			document->addUndoable(hatch);
			document->endUndoCycle();
		}
		hatch->update();

		graphicView->redraw(RS2::RedrawDrawing);

		RS_DIALOGFACTORY->commandMessage(tr("Hatch created successfully."));
	}
	else {
		delete hatch;
		hatch = NULL;
		RS_DIALOGFACTORY->commandMessage(tr("Invalid hatch area. Please check that "
		"the entities chosen form one or more closed contours."));
	}
    //}
}
Example #8
0
/**
 * Updates the Inserts (letters) of this text. Called when the
 * text or it's data, position, alignment, .. changes.
 * This method also updates the usedTextWidth / usedTextHeight property.
 */
void RS_MText::update() {

    RS_DEBUG->print("RS_Text::update");

    clear();

    if (isUndone()) {
        return;
    }

    usedTextWidth = 0.0;
    usedTextHeight = 0.0;

    RS_Font* font = RS_FONTLIST->requestFont(data.style);

    if (font==NULL) {
        return;
    }

    RS_Vector letterPos = RS_Vector(0.0, -9.0);
    RS_Vector letterSpace = RS_Vector(font->getLetterSpacing(), 0.0);
    RS_Vector space = RS_Vector(font->getWordSpacing(), 0.0);
    int lineCounter = 0;

    // Every single text line gets stored in this entity container
    //  so we can move the whole line around easely:
    RS_EntityContainer* oneLine = new RS_EntityContainer(this);

    // First every text line is created with
    //   alignement: top left
    //   angle: 0
    //   height: 9.0
    // Rotation, scaling and centering is done later

    // For every letter:
    for (int i=0; i<(int)data.text.length(); ++i) {
        bool handled = false;
        switch (data.text.at(i).unicode()) {
        case 0x0A:
            // line feed:
            updateAddLine(oneLine, lineCounter++);
            oneLine = new RS_EntityContainer(this);
            letterPos = RS_Vector(0.0, -9.0);
            break;

        case 0x20:
            // Space:
            letterPos+=space;
            break;

        case 0x5C: {
                // code (e.g. \S, \P, ..)
                i++;
                int ch = data.text.at(i).unicode();
                switch (ch) {
                case 'P':
                    updateAddLine(oneLine, lineCounter++);
                    oneLine = new RS_EntityContainer(this);
                    letterPos = RS_Vector(0.0, -9.0);
                    handled = true;
                    break;
                    case 'f':
                    case 'F':
                    //font change
                    // \f{symbol} changes font to symbol
                    // \f{} sets font to standard
                {
                    i++;
                    if(data.text.at(i).unicode()!='{') {
                        i--;
                        continue;
                    }
                    int j=data.text.indexOf('}',i);
                    if(j>i){
                        //
                        QString fontName;
                        if(j==i+1)
                            fontName="standard";
                        else
                            fontName=data.text.mid(i+1,j-i-1);
                        RS_Font* fontNew = RS_FONTLIST->requestFont(
                                    fontName
                                    );
                        if(fontNew != NULL) {
                            font=fontNew;
                        }
                        if(font==NULL) font = RS_FONTLIST->requestFont("standard");
                        i=j;
                    }
                }
                        continue;

                case 'S': {
                        QString up;
                        QString dw;
                        //letterPos += letterSpace;

                        // get upper string:
                        i++;
                        while (data.text.at(i).unicode()!='^' &&
                                                       //data.text.at(i).unicode()!='/' &&
                                                       data.text.at(i).unicode()!='\\' &&
                                                       //data.text.at(i).unicode()!='#' &&
                                i<(int)data.text.length()) {
                            up += data.text.at(i);
                            i++;
                        }

                        i++;

                                                if (data.text.at(i-1).unicode()=='^' &&
                                                     data.text.at(i).unicode()==' ') {
                                                        i++;
                                                }

                        // get lower string:
                        while (data.text.at(i).unicode()!=';' &&
                                i<(int)data.text.length()) {
                            dw += data.text.at(i);
                            i++;
                        }

                        // add texts:
                        RS_MText* upper =
                            new RS_MText(
                                oneLine,
                                RS_MTextData(letterPos + RS_Vector(0.0,9.0),
                                            4.0, 100.0, RS_MTextData::VATop, RS_MTextData::HALeft,
                                            RS_MTextData::LeftToRight, RS_MTextData::Exact,
                                            1.0, up, data.style,
                                            0.0, RS2::Update));
                                            upper->setLayer(NULL);
                        upper->setPen(RS_Pen(RS2::FlagInvalid));
                        oneLine->addEntity(upper);

                        RS_MText* lower =
                            new RS_MText(
                                oneLine,
                                RS_MTextData(letterPos+RS_Vector(0.0,4.0),
                                            4.0, 100.0, RS_MTextData::VATop, RS_MTextData::HALeft,
                                            RS_MTextData::LeftToRight, RS_MTextData::Exact,
                                            1.0, dw, data.style,
                                            0.0, RS2::Update));
                                            lower->setLayer(NULL);
                        lower->setPen(RS_Pen(RS2::FlagInvalid));
                        oneLine->addEntity(lower);

                        // move cursor:
                        upper->calculateBorders();
                        lower->calculateBorders();

                        double w1 = upper->getSize().x;
                        double w2 = lower->getSize().x;

                        if (w1>w2) {
                            letterPos += RS_Vector(w1, 0.0);
                        } else {
                            letterPos += RS_Vector(w2, 0.0);
                        }
                        letterPos += letterSpace;
                    }
                    handled = true;
                    break;

                default:
                    i--;
                    break;
                }
            }
            //if char is not handled continue in default: statement
            if (handled)
                break;

        default: {
                // One Letter:
                QString letterText = QString(data.text.at(i));
                if (font->findLetter(letterText) == NULL) {
                    RS_DEBUG->print("RS_Text::update: missing font for letter( %s ), replaced it with QChar(0xfffd)",qPrintable(letterText));
                    letterText = QChar(0xfffd);
                }
//                if (font->findLetter(QString(data.text.at(i))) != NULL) {

                                        RS_DEBUG->print("RS_Text::update: insert a "
                                          "letter at pos: %f/%f", letterPos.x, letterPos.y);

                    RS_InsertData d(letterText,
                                    letterPos,
                                    RS_Vector(1.0, 1.0),
                                    0.0,
                                    1,1, RS_Vector(0.0,0.0),
                                    font->getLetterList(), RS2::NoUpdate);

                    RS_Insert* letter = new RS_Insert(this, d);
                    RS_Vector letterWidth;
                    letter->setPen(RS_Pen(RS2::FlagInvalid));
                    letter->setLayer(NULL);
                    letter->update();
                    letter->forcedCalculateBorders();

                                        // until 2.0.4.5:
                    //letterWidth = RS_Vector(letter->getSize().x, 0.0);
                                        // from 2.0.4.6:
                    letterWidth = RS_Vector(letter->getMax().x-letterPos.x, 0.0);
                    if (letterWidth.x < 0)
                        letterWidth.x = -letterSpace.x;

                    oneLine->addEntity(letter);

                    // next letter position:
                    letterPos += letterWidth;
                    letterPos += letterSpace;
//                }
            }
            break;
        }
    }

    double tt = updateAddLine(oneLine, lineCounter);
    if (data.valign == RS_MTextData::VABottom) {
        RS_Vector ot = RS_Vector(0.0,-tt).rotate(data.angle);
        RS_EntityContainer::move(ot);
    }

    usedTextHeight -= data.height*data.lineSpacingFactor*5.0/3.0
                      - data.height;
    forcedCalculateBorders();

    RS_DEBUG->print("RS_Text::update: OK");
}
Example #9
0
/**
 * Updates the Hatch. Called when the
 * hatch or it's data, position, alignment, .. changes.
 */
void RS_Hatch::update() {
        RS_DEBUG->print("RS_Hatch::update");
        RS_DEBUG->print("RS_Hatch::update: contour has %d loops", count());

    if (updateRunning) {
        return;
    }

    if (updateEnabled==false) {
        return;
    }

    if (data.solid==true) {
        calculateBorders();
        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_Debug::D_WARNING,
                        "RS_Hatch::update: invalid contour in hatch found");
        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");

    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();
    forcedCalculateBorders();
    RS_DEBUG->print("RS_Hatch::update: scaling pattern: OK");

    // 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->forcedCalculateBorders();

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

    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++) {
        for (int py=py1; py<=py2; py++) {
            for (RS_Entity* e=pat->firstEntity(); e!=NULL;
                    e=pat->nextEntity()) {

                RS_Entity* te = e->clone();
                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);
            }
        }
    }

    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;
    RS_Ellipse* ellipse = 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;

        switch(e->rtti()){
        case RS2::EntityLine:
            line=static_cast<RS_Line*>(e);
            startPoint = line->getStartpoint();
            endPoint = line->getEndpoint();
            break;
        case RS2::EntityArc:
            arc=static_cast<RS_Arc*>(e);
            startPoint = arc->getStartpoint();
            endPoint = arc->getEndpoint();
            center = arc->getCenter();
            reversed = arc->isReversed();
            break;
        case RS2::EntityCircle:
            circle=static_cast<RS_Circle*>(e);
            startPoint = circle->getCenter()
                    + RS_Vector(circle->getRadius(), 0.0);
            endPoint = startPoint;
            center = circle->getCenter();
            break;
        case RS2::EntityEllipse:
            ellipse = static_cast<RS_Ellipse*>(e);
            startPoint = ellipse->getStartpoint();
            endPoint = ellipse->getEndpoint();
            center = ellipse->getCenter();
            reversed = ellipse->isReversed();
            break;
        default:
            continue;
        }

        // getting all intersections of this pattern line with the contour:
        QList<std::shared_ptr<RS_Vector> > is;
        is.append(std::shared_ptr<RS_Vector>(new RS_Vector(startPoint)));

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

            if (loop->isContainer()) {
                for (RS_Entity* p=((RS_EntityContainer*)loop)->firstEntity();
                        p!=NULL;
                        p=((RS_EntityContainer*)loop)->nextEntity()) {

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

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

        is.append(std::shared_ptr<RS_Vector>(new RS_Vector(endPoint)));

        // sort the intersection points into is2:
        RS_Vector sp = startPoint;
        double sa = center.angleTo(sp);
        if(ellipse != NULL) sa=ellipse->getEllipseAngle(sp);
        QList<std::shared_ptr<RS_Vector> > is2;
        bool done;
        double minDist;
        double dist = 0.0;
        std::shared_ptr<RS_Vector> av;
        std::shared_ptr<RS_Vector> v;
        RS_Vector last = RS_Vector(false);
        do {
            done = true;
            minDist = RS_MAXDOUBLE;
            av.reset();
            for (int i = 0; i < is.size(); ++i) {
                v = is.at(i);
                double a;
                switch(e->rtti()){
                case RS2::EntityLine:
                    dist = sp.distanceTo(*v);
                    break;
                case RS2::EntityArc:
                case RS2::EntityCircle:
                    a = center.angleTo(*v);
                    dist = reversed?
                                fmod(sa - a + 2.*M_PI,2.*M_PI):
                                fmod(a - sa + 2.*M_PI,2.*M_PI);
                    break;
                case RS2::EntityEllipse:
                    a = ellipse->getEllipseAngle(*v);
                    dist = reversed?
                                fmod(sa - a + 2.*M_PI,2.*M_PI):
                                fmod(a - sa + 2.*M_PI,2.*M_PI);
                    break;
                default:
                    break;

                }

                if (dist<minDist) {
                    minDist = dist;
                    done = false;
                    av = v;
                }
            }

            // copy to sorted list, removing double points
            if (!done && av.get()!=NULL) {
                if (last.valid==false || last.distanceTo(*av)>RS_TOLERANCE) {
                    is2.append(std::shared_ptr<RS_Vector>(new RS_Vector(*av)));
                    last = *av;
                }
#if QT_VERSION < 0x040400
                emu_qt44_removeOne(is, av);
#else
                is.removeOne(av);
#endif

                av.reset();
            }
        } while(!done);

        // add small cut lines / arcs to tmp2:
            for (int i = 1; i < is2.size(); ++i) {
                auto v1 = is2.at(i-1);
                auto v2 = is2.at(i);

                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)));
                }
            }

    }

    // 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 (RS_Information::isPointInsideContour(
                        middlePoint,
                        this, &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);
            }
        }
    }

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

    forcedCalculateBorders();

    // deactivate contour:
    activateContour(false);

    updateRunning = false;

    RS_DEBUG->print("RS_Hatch::update: OK");
}
Example #10
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;
}