Ejemplo n.º 1
0
void CenterSystem::update(float delta){
  for(int iterator = 0; iterator < numEntities(); iterator++){
    Entity *ent = entityAt(iterator);

    if(ent->hasComponent(COMPONENT_POSITION) && ent->hasComponent(COMPONENT_CENTER)){
      Center *c = static_cast<Center*>(ent->getComponent(COMPONENT_CENTER));
      Position *pos = static_cast<Position*>(ent->getComponent(COMPONENT_POSITION));

      if(c->getHorizontal())
        pos->setX(width/2);

      if(c->getVertical())
        pos->setY(height/2);
    }

  };
}
Ejemplo n.º 2
0
/**
  * this should handle modifyOffset
  *@ coord, indicate direction of offset
  *@ distance of offset
  *
  *@Author, Dongxu Li
  */
bool RS_Polyline::offset(const RS_Vector& coord, const double& distance){
    double dist;
    //find the nearest one
    int length=count();
		std::vector<RS_Vector> intersections(length);
    if(length>1){//sort the polyline entity start/end point order
        int i(0);
        double d0,d1;
        RS_Entity* en0(entityAt(0));
        RS_Entity* en1(entityAt(1));

        RS_Vector vStart(en0->getStartpoint());
        RS_Vector vEnd(en0->getEndpoint());
        en1->getNearestEndpoint(vStart,&d0);
        en1->getNearestEndpoint(vEnd,&d1);
        if(d0<d1) en0->revertDirection();
        for(i=1;i<length;en0=en1){
                //linked to head-tail chain
            en1=entityAt(i);
            vStart=en1->getStartpoint();
            vEnd=en1->getEndpoint();
            en0->getNearestEndpoint(vStart,&d0);
            en0->getNearestEndpoint(vEnd,&d1);
            if(d0>d1) en1->revertDirection();
            intersections[i-1]=(en0->getEndpoint()+en1->getStartpoint())*0.5;
            i++;
        }

    }
    RS_Entity* en(getNearestEntity(coord, &dist, RS2::ResolveNone));
    if(en==NULL) return false;
    int indexNearest=findEntity(en);
    //        RS_Vector vp(en->getNearestPointOnEntity(coord,false));
    //        RS_Vector direction(en->getTangentDirection(vp));
    //        RS_Vector vp1(-direction.y,direction.x);//normal direction
    //        double a2(vp1.squared());
    //        if(a2<RS_TOLERANCE2) return false;
    //        vp1 *= distance/sqrt(a2);
    //        move(vp1);
    //        return true;

    RS_Polyline* pnew= static_cast<RS_Polyline*>(clone());
    int i;
    i=indexNearest;
    int previousIndex(i);
    pnew->entityAt(i)->offset(coord,distance);
    RS_Vector vp;
    //offset all
    //fixme, this is too ugly
    for(i=indexNearest-1;i>=0;i--){
        RS_VectorSolutions sol0=RS_Information::getIntersection(pnew->entityAt(previousIndex),entityAt(i),true);
//        RS_VectorSolutions sol1;
        double dmax(RS_TOLERANCE15);
        RS_Vector trimP(false);
		for(const RS_Vector& vp: sol0){

			double d0( (vp - pnew->entityAt(previousIndex)->getStartpoint()).squared());//potential bug, need to trim better
            if(d0>dmax) {
                dmax=d0;
				trimP=vp;
            }
        }
        if(trimP.valid){
            static_cast<RS_AtomicEntity*>(pnew->entityAt(previousIndex))->trimStartpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimEndpoint(trimP);
            vp=pnew->entityAt(previousIndex)->getMiddlePoint();
        }else{
            vp=pnew->entityAt(previousIndex)->getStartpoint();
            vp.rotate(entityAt(previousIndex)->getStartpoint(),entityAt(i)->getDirection2()-entityAt(previousIndex)->getDirection1()+M_PI);
        }
        pnew->entityAt(i)->offset(vp,distance);
        previousIndex=i;
    }

    previousIndex=indexNearest;
    for(i=indexNearest+1;i<length;i++){
        RS_VectorSolutions sol0=RS_Information::getIntersection(pnew->entityAt(previousIndex),entityAt(i),true);
//        RS_VectorSolutions sol1;
        double dmax(RS_TOLERANCE15);
        RS_Vector trimP(false);
		for(const RS_Vector& vp: sol0){
			double d0( (vp - pnew->entityAt(previousIndex)->getEndpoint()).squared());//potential bug, need to trim better
            if(d0>dmax) {
                dmax=d0;
				trimP=vp;
            }
        }
        if(trimP.valid){
            static_cast<RS_AtomicEntity*>(pnew->entityAt(previousIndex))->trimEndpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimStartpoint(trimP);
            vp=pnew->entityAt(previousIndex)->getMiddlePoint();
        }else{
            vp=pnew->entityAt(previousIndex)->getEndpoint();
            vp.rotate(entityAt(previousIndex)->getEndpoint(),entityAt(i)->getDirection1()-entityAt(previousIndex)->getDirection2()+M_PI);
        }
        pnew->entityAt(i)->offset(vp,distance);
        previousIndex=i;
    }
    //trim
    //connect and trim        RS_Modification m(*container, graphicView);
    for(i=0;i<length-1;i++){
        RS_VectorSolutions sol0=RS_Information::getIntersection(pnew->entityAt(i),pnew->entityAt(i+1),true);
        if(sol0.getNumber()==0) {
            sol0=RS_Information::getIntersection(pnew->entityAt(i),pnew->entityAt(i+1));
//            RS_Vector vp0(pnew->entityAt(i)->getEndpoint());
//            RS_Vector vp1(pnew->entityAt(i+1)->getStartpoint());
//            double a0(intersections.at(i).angleTo(vp0));
//            double a1(intersections.at(i).angleTo(vp1));
            RS_VectorSolutions sol1;
			for(const RS_Vector& vp: sol0){
				if(RS_Math::isAngleBetween(intersections.at(i).angleTo(vp),
                                           pnew->entityAt(i)->getDirection2(),
                                           pnew->entityAt(i+1)->getDirection1(),
                                           false)==false){
					sol1.push_back(vp);
                }
            }
            if(sol1.getNumber()==0) continue;
            RS_Vector trimP(sol1.getClosest(intersections.at(i)));
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimEndpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i+1))->trimStartpoint(trimP);
        }else{
            RS_Vector trimP(sol0.getClosest(pnew->entityAt(i)->getStartpoint()));
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimEndpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i+1))->trimStartpoint(trimP);
        }

    }

    *this = *pnew;
    return true;


}
/**
 * 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;
}
Ejemplo n.º 4
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;
}