/** * Selects this entity. */ bool RS_EntityContainer::setSelected(bool select) { // This entity's select: if (RS_Entity::setSelected(select)) { // All sub-entity's select: for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { if (e->isVisible()) { e->setSelected(select); } } return true; } else { return false; } }
/** * Counts the entities on the given layer. */ unsigned long int RS_Graphic::countLayerEntities(RS_Layer* layer) { int c=0; if (layer!=NULL) { for (RS_Entity* t=firstEntity(RS2::ResolveNone); t!=NULL; t=nextEntity(RS2::ResolveNone)) { if (t->getLayer()!=NULL && t->getLayer()->getName()==layer->getName()) { c+=t->countDeep(); } } } return c; }
/** * Recalculates the borders of this entity container. */ void RS_EntityContainer::calculateBorders() { RS_DEBUG->print("RS_EntityContainer::calculateBorders"); resetBorders(); for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { RS_Layer* layer = e->getLayer(); RS_DEBUG->print("RS_EntityContainer::calculateBorders: " "isVisible: %d", (int)e->isVisible()); if (e->isVisible() && (layer==NULL || !layer->isFrozen())) { e->calculateBorders(); adjustBorders(e); } } RS_DEBUG->print("RS_EntityContainer::calculateBorders: size 1: %f,%f", getSize().x, getSize().y); // needed for correcting corrupt data (PLANS.dxf) if (minV.x>maxV.x || minV.x>RS_MAXDOUBLE || maxV.x>RS_MAXDOUBLE || minV.x<RS_MINDOUBLE || maxV.x<RS_MINDOUBLE) { minV.x = 0.0; maxV.x = 0.0; } if (minV.y>maxV.y || minV.y>RS_MAXDOUBLE || maxV.y>RS_MAXDOUBLE || minV.y<RS_MINDOUBLE || maxV.y<RS_MINDOUBLE) { minV.y = 0.0; maxV.y = 0.0; } RS_DEBUG->print("RS_EntityCotnainer::calculateBorders: size: %f,%f", getSize().x, getSize().y); //RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y); //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y); //RS_Entity::calculateBorders(); }
RS_Vector RS_EntityContainer::getNearestMiddle(const RS_Vector& coord, double* dist, int middlePoints ) { double minDist = RS_MAXDOUBLE; // minimum measured distance double curDist = RS_MAXDOUBLE; // currently measured distance RS_Vector closestPoint; // closest found endpoint RS_Vector point; // endpoint found //std::cout<<"RS_EntityContainer::getNearestMiddle() middlePoints="<<middlePoints<<std::endl; for (RS_Entity* en = firstEntity(RS2::ResolveAll); en != NULL; en = nextEntity(RS2::ResolveAll)) { if (en->isVisible() && ! en->isContainer()) { if ( en->getParent()->rtti() == RS2::EntityInsert /**Insert*/ || en->rtti() == RS2::EntityPoint /**Point*/ || en->getParent()->rtti() == RS2::EntitySpline || en->getParent()->rtti() == RS2::EntityText /**< Text 15*/ || en->getParent()->rtti() == RS2::EntityDimAligned /**< Aligned Dimension */ || en->getParent()->rtti() == RS2::EntityDimLinear /**< Linear Dimension */ || en->getParent()->rtti() == RS2::EntityDimRadial /**< Radial Dimension */ || en->getParent()->rtti() == RS2::EntityDimDiametric /**< Diametric Dimension */ || en->getParent()->rtti() == RS2::EntityDimAngular /**< Angular Dimension */ || en->getParent()->rtti() == RS2::EntityDimLeader /**< Leader Dimension */ ){//no middle point for Spline, Insert, text, Dim continue; } //std::cout<<"en->rtti()="<<en->rtti()<<" en->getParent()->rtti()="<< en->getParent()->rtti() <<std::endl; point = en->getNearestMiddle(coord, &curDist, middlePoints); if (curDist<minDist) { closestPoint = point; minDist = curDist; } } } if (dist!=NULL) { *dist = curDist; } return closestPoint; }
void RS_EntityContainer::stretch(RS_Vector firstCorner, RS_Vector secondCorner, RS_Vector offset) { if (getMin().isInWindow(firstCorner, secondCorner) && getMax().isInWindow(firstCorner, secondCorner)) { move(offset); } else { for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { e->stretch(firstCorner, secondCorner, offset); } } // some entitiycontainers might need an update (e.g. RS_Leader): update(); }
/** * @return The intersection which is closest to 'coord' */ RS_Vector RS_EntityContainer::getNearestIntersection(const RS_Vector& coord, double* dist) { double minDist = RS_MAXDOUBLE; // minimum measured distance double curDist; // currently measured distance RS_Vector closestPoint(false); // closest found endpoint RS_Vector point; // endpoint found RS_VectorSolutions sol; RS_Entity* closestEntity; closestEntity = getNearestEntity(coord, NULL, RS2::ResolveAll); if (closestEntity!=NULL) { for (RS_Entity* en = firstEntity(RS2::ResolveAll); en != NULL; en = nextEntity(RS2::ResolveAll)) { if (en->isVisible() && en!=closestEntity) { sol = RS_Information::getIntersection(closestEntity, en, true); for (int i=0; i<4; i++) { point = sol.get(i); if (point.valid) { curDist = coord.distanceTo(point); if (curDist<minDist) { closestPoint = point; minDist = curDist; if (dist!=NULL) { *dist = curDist; } } } } } } //} } return closestPoint; }
/** * @return Total length of all entities in this container. */ double RS_EntityContainer::getLength() { double ret = 0.0; for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { if (e->isVisible()) { double l = e->getLength(); if (l<0.0) { ret = -1.0; break; } else { ret += l; } } } return ret; }
RS_VectorSolutions RS_Polyline::getRefPoints() { RS_VectorSolutions ret(count()+1); int i=0; ret.set(0, data.startpoint); i++; for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e = nextEntity(RS2::ResolveNone), i++) { if (e->isAtomic()) { ret.set(i, ((RS_AtomicEntity*)e)->getEndpoint()); } } ret.set(count(), data.endpoint); return ret; }
/** * Removes the given layer and undoes all entities on it. */ void RS_Graphic::removeLayer(RS_Layer* layer) { if (layer!=NULL && layer->getName()!="0") { // remove all entities on that layer: startUndoCycle(); for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { if (e->getLayer()!=NULL && e->getLayer()->getName()==layer->getName()) { e->setUndoState(true); e->setLayer("0"); addUndoable(e); } } endUndoCycle(); // remove all entities in blocks that are on that layer: for (int bi=0; bi<blockList.count(); bi++) { RS_Block* blk = blockList.at(bi); if (blk!=NULL) { for (RS_Entity* e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone)) { if (e->getLayer()!=NULL && e->getLayer()->getName()==layer->getName()) { e->setUndoState(true); e->setLayer("0"); //addUndoable(e); } } } } layerList.remove(layer); } }
/** * Activates of deactivates the hatch boundary. */ void RS_Hatch::activateContour(bool on) { RS_DEBUG->print("RS_Hatch::activateContour: %d", (int)on); for (RS_Entity* e=firstEntity(); e!=NULL; e=nextEntity()) { if (!e->isUndone()) { if (!e->getFlag(RS2::FlagTemp)) { RS_DEBUG->print("RS_Hatch::activateContour: set visible"); e->setVisible(on); } else { RS_DEBUG->print("RS_Hatch::activateContour: entity temp"); } } else { RS_DEBUG->print("RS_Hatch::activateContour: entity undone"); } } RS_DEBUG->print("RS_Hatch::activateContour: OK"); }
/** * Slightly optimized drawing for polylines. */ void RS_Polyline::draw(RS_Painter* painter, RS_GraphicView* view, double /*patternOffset*/) { if (painter==NULL || view==NULL) { return; } // draw first entity and set correct pen: RS_Entity* e = firstEntity(RS2::ResolveNone); view->drawEntity(e); // draw subsequent entities with same pen: for (RS_Entity* e=nextEntity(RS2::ResolveNone); e!=NULL; e = nextEntity(RS2::ResolveNone)) { view->drawEntityPlain(e); } }
double RS_EntityContainer::getDistanceToPoint(const RS_Vector& coord, RS_Entity** entity, RS2::ResolveLevel level, double solidDist) { RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint"); double minDist = RS_MAXDOUBLE; // minimum measured distance double curDist; // currently measured distance RS_Entity* closestEntity = NULL; // closest entity found RS_Entity* subEntity = NULL; //int k=0; for (RS_Entity* e = firstEntity(level); e != NULL; e = nextEntity(level)) { if (e->isVisible()) { RS_DEBUG->print("entity: getDistanceToPoint"); RS_DEBUG->print("entity: %d", e->rtti()); curDist = e->getDistanceToPoint(coord, &subEntity, level, solidDist); RS_DEBUG->print("entity: getDistanceToPoint: OK"); if (curDist<minDist) { if (level!=RS2::ResolveAll) { closestEntity = e; } else { closestEntity = subEntity; } minDist = curDist; } } } if (entity!=NULL) { *entity = closestEntity; } RS_DEBUG->print("RS_EntityContainer::getDistanceToPoint: OK"); return minDist; }
/** * @return The intersection which is closest to 'coord' */ RS_Vector RS_EntityContainer::getNearestIntersection(const RS_Vector& coord, double* dist) { double minDist = RS_MAXDOUBLE; // minimum measured distance double curDist = RS_MAXDOUBLE; // currently measured distance RS_Vector closestPoint(false); // closest found endpoint RS_Vector point; // endpoint found RS_VectorSolutions sol; RS_Entity* closestEntity; closestEntity = getNearestEntity(coord, nullptr, RS2::ResolveAllButTextImage); if (closestEntity) { for (RS_Entity* en = firstEntity(RS2::ResolveAllButTextImage); en; en = nextEntity(RS2::ResolveAllButTextImage)) { if ( !en->isVisible() || en->getParent()->ignoredOnModification() ){ continue; } sol = RS_Information::getIntersection(closestEntity, en, true); point=sol.getClosest(coord,&curDist,nullptr); if(sol.getNumber()>0 && curDist<minDist){ closestPoint=point; minDist=curDist; } } } if(dist && closestPoint.valid) { *dist = minDist; } return closestPoint; }
/** * Slightly optimized drawing for polylines. */ void RS_Polyline::draw(RS_Painter* painter,RS_GraphicView* view, double& /*patternOffset*/) { if (!view) return; // draw first entity and set correct pen: RS_Entity* e = firstEntity(RS2::ResolveNone); // We get the pen from the entitycontainer and apply it to the // first line so that subsequent line are draw in the right color //prevent segfault if polyline is empty if (e) { RS_Pen p=this->getPen(true); e->setPen(p); double patternOffset=0.; view->drawEntity(painter, e, patternOffset); e = nextEntity(RS2::ResolveNone); while(e) { view->drawEntityPlain(painter, e, patternOffset); e = nextEntity(RS2::ResolveNone); } } }
void RS_Spline::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) { if (painter==nullptr || view==nullptr) { return; } RS_Entity* e=firstEntity(RS2::ResolveNone); if (e) { RS_Pen p=this->getPen(true); e->setPen(p); double patternOffset(0.0); view->drawEntity(painter, e, patternOffset); //RS_DEBUG->print("offset: %f\nlength was: %f", offset, e->getLength()); e = nextEntity(RS2::ResolveNone); while(e) { view->drawEntityPlain(painter, e, patternOffset); e = nextEntity(RS2::ResolveNone); //RS_DEBUG->print("offset: %f\nlength was: %f", offset, e->getLength()); } } }
/** * Recalculates the borders of this entity container including * invisible entities. */ void RS_EntityContainer::forcedCalculateBorders() { //RS_DEBUG->print("RS_EntityContainer::calculateBorders"); resetBorders(); for (RS_Entity* e=firstEntity(RS2::ResolveNone); e!=NULL; e=nextEntity(RS2::ResolveNone)) { //RS_Layer* layer = e->getLayer(); if (e->isContainer()) { ((RS_EntityContainer*)e)->forcedCalculateBorders(); } else { e->calculateBorders(); } adjustBorders(e); } // needed for correcting corrupt data (PLANS.dxf) if (minV.x>maxV.x || minV.x>RS_MAXDOUBLE || maxV.x>RS_MAXDOUBLE || minV.x<RS_MINDOUBLE || maxV.x<RS_MINDOUBLE) { minV.x = 0.0; maxV.x = 0.0; } if (minV.y>maxV.y || minV.y>RS_MAXDOUBLE || maxV.y>RS_MAXDOUBLE || minV.y<RS_MINDOUBLE || maxV.y<RS_MINDOUBLE) { minV.y = 0.0; maxV.y = 0.0; } //RS_DEBUG->print(" borders: %f/%f %f/%f", minV.x, minV.y, maxV.x, maxV.y); //printf("borders: %lf/%lf %lf/%lf\n", minV.x, minV.y, maxV.x, maxV.y); //RS_Entity::calculateBorders(); }
/** * Overrides drawing of subentities. This is only ever called for solid fills. */ void RS_Hatch::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) { if (!data.solid) { for (RS_Entity* se=firstEntity(); se!=NULL; se = nextEntity()) { view->drawEntity(painter,se); } return; } QPainterPath path; QList<QPolygon> paClosed; QPolygon pa; // QPolygon jp; // jump points // loops: if (needOptimization==true) { for (RS_Entity* l=firstEntity(RS2::ResolveNone); l!=NULL; l=nextEntity(RS2::ResolveNone)) { if (l->rtti()==RS2::EntityContainer) { RS_EntityContainer* loop = (RS_EntityContainer*)l; loop->optimizeContours(); } } needOptimization = false; } // loops: for (RS_Entity* l=firstEntity(RS2::ResolveNone); l!=NULL; l=nextEntity(RS2::ResolveNone)) { l->setLayer(getLayer()); if (l->rtti()==RS2::EntityContainer) { RS_EntityContainer* loop = (RS_EntityContainer*)l; // edges: for (RS_Entity* e=loop->firstEntity(RS2::ResolveNone); e!=NULL; e=loop->nextEntity(RS2::ResolveNone)) { e->setLayer(getLayer()); switch (e->rtti()) { case RS2::EntityLine: { QPoint pt1(RS_Math::round(view->toGuiX(e->getStartpoint().x)), RS_Math::round(view->toGuiY(e->getStartpoint().y))); QPoint pt2(RS_Math::round(view->toGuiX(e->getEndpoint().x)), RS_Math::round(view->toGuiY(e->getEndpoint().y))); // if (! (pa.size()>0 && (pa.last() - pt1).manhattanLength()<=2)) { // jp<<pt1; // } pa<<pt1<<pt2; } break; case RS2::EntityArc: { // QPoint pt1(RS_Math::round(view->toGuiX(e->getStartpoint().x)), // RS_Math::round(view->toGuiY(e->getStartpoint().y))); // if (! (pa.size()>0 && (pa.last() - pt1).manhattanLength()<=2)) { // jp<<pt1; // } QPolygon pa2; RS_Arc* arc=static_cast<RS_Arc*>(e); painter->createArc(pa2, view->toGui(arc->getCenter()), view->toGuiDX(arc->getRadius()), arc->getAngle1(), arc->getAngle2(), arc->isReversed()); pa<<pa2; } break; case RS2::EntityCircle: { RS_Circle* circle = static_cast<RS_Circle*>(e); // QPoint pt1(RS_Math::round(view->toGuiX(circle->getCenter().x+circle->getRadius())), // RS_Math::round(view->toGuiY(circle->getCenter().y))); // if (! (pa.size()>0 && (pa.last() - pt1).manhattanLength()<=2)) { // jp<<pt1; // } RS_Vector c=view->toGui(circle->getCenter()); double r=view->toGuiDX(circle->getRadius()); #if QT_VERSION >= 0x040400 path.addEllipse(QPoint(c.x,c.y),r,r); #else path.addEllipse(c.x - r, c.y + r, 2.*r, 2.*r); // QPolygon pa2; // painter->createArc(pa2, view->toGui(circle->getCenter()), // view->toGuiDX(circle->getRadius()), // 0.0, // 2*M_PI, // false); // pa<<pa2; #endif } break; case RS2::EntityEllipse: if(static_cast<RS_Ellipse*>(e)->isArc()) { QPolygon pa2; auto ellipse=static_cast<RS_Ellipse*>(e); painter->createEllipse(pa2, view->toGui(ellipse->getCenter()), view->toGuiDX(ellipse->getMajorRadius()), view->toGuiDX(ellipse->getMinorRadius()), ellipse->getAngle(), ellipse->getAngle1(), ellipse->getAngle2(), ellipse->isReversed() ); pa<<pa2; }else{ QPolygon pa2; auto ellipse=static_cast<RS_Ellipse*>(e); painter->createEllipse(pa2, view->toGui(ellipse->getCenter()), view->toGuiDX(ellipse->getMajorRadius()), view->toGuiDX(ellipse->getMinorRadius()), ellipse->getAngle(), ellipse->getAngle1(), ellipse->getAngle2(), ellipse->isReversed() ); path.addPolygon(pa2); } break; default: break; } if( pa.size()>2 && pa.first() == pa.last()) { paClosed<<pa; pa.clear(); } } } } if(pa.size()>2){ pa<<pa.first(); paClosed<<pa; } for(int i=0;i<paClosed.size();i++){ path.addPolygon(paClosed.at(i)); } painter->setBrush(painter->getPen().getColor()); painter->disablePen(); painter->drawPath(path); // pa<<jp; // painter->setBrush(painter->getPen().getColor()); // painter->disablePen(); // painter->drawPolygon(pa); }
/** * 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!=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; 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==NULL) { 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"); updateError = HATCH_AREA_TOO_BIG; 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); f = copy->getMax().y/pat->getSize().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 (RS_Entity* e=pat->firstEntity(); e!=NULL; e=pat->nextEntity()) { RS_Entity* te=e->clone(); te->move(dvx*px + dvy*py); 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=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; 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"); }
/** * 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; }