void Doc_plugin_interface::getCurrentLayerProperties(QColor *c, DPI::LineWidth *w, DPI::LineType *t){ RS_Pen pen = docGr->getActiveLayer()->getPen(); RS_Color col = pen.getColor(); c->setRgb(col.red(), col.green(), col.blue()); *w = static_cast<DPI::LineWidth>(pen.getWidth()); *t = static_cast<DPI::LineType>(pen.getLineType()); }
void Doc_plugin_interface::getCurrentLayerProperties(QColor *c, QString *w, QString *t){ RS_Pen pen = docGr->getActiveLayer()->getPen(); RS_Color col = pen.getColor(); c->setRgb(col.red(), col.green(), col.blue()); w->clear(); w->append(Converter.lw2str(pen.getWidth())); t->clear(); t->append(Converter.lt2str(pen.getLineType())); }
/** * Gets the pen needed to draw this entity. * The attributes can also come from the layer this entity is on * if the flags are set accordingly. * * @param resolve true: Resolve the pen to a drawable pen (e.g. the pen * from the layer or parent..) * false: Don't resolve and return a pen or ByLayer, ByBlock, ... * * @return Pen for this entity. */ RS_Pen RS_Entity::getPen(bool resolve) const { if (!resolve) { return pen; } else { RS_Pen p = pen; RS_Layer* l = getLayer(true); // use parental attributes (e.g. vertex of a polyline, block // entities when they are drawn in block documents): if (!p.isValid() || p.getColor().isByBlock()) { if (parent!=NULL) { p = parent->getPen(); } } // use layer attributes: else if (l!=NULL) { // layer is "ByBlock": /*if (layer->getName()=="ByBlock" && getBlockOrInsert()!=NULL) { p = getBlockOrInsert()->getPen(); } else {*/ // use layer's color: if (p.getColor().isByLayer()) { p.setColor(l->getPen().getColor()); } // use layer's width: if (p.getWidth()==RS2::WidthByLayer) { p.setWidth(l->getPen().getWidth()); } // use layer's linetype: if (p.getLineType()==RS2::LineByLayer) { p.setLineType(l->getPen().getLineType()); } //} } return p; } }
void RS_Arc::draw(RS_Painter* painter, RS_GraphicView* view, double /*patternOffset*/) { if (painter==NULL || view==NULL) { return; } //double styleFactor = getStyleFactor(); // simple style-less lines if (getPen().getLineType()==RS2::SolidLine || isSelected() || view->getDrawingMode()==RS2::ModePreview) { painter->drawArc(view->toGui(getCenter()), getRadius() * view->getFactor().x, getAngle1(), getAngle2(), isReversed()); } else { double styleFactor = getStyleFactor(view); if (styleFactor<0.0) { painter->drawArc(view->toGui(getCenter()), getRadius() * view->getFactor().x, getAngle1(), getAngle2(), isReversed()); return; } // Pattern: RS_LineTypePattern* pat; if (isSelected()) { pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { return; } if (getRadius()<1.0e-6) { return; } // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); double a1; double a2; if (data.reversed) { a2 = getAngle1(); a1 = getAngle2(); } else { a1 = getAngle1(); a2 = getAngle2(); } double* da; // array of distances in x. int i; // index counter double length = getAngleLength(); // create scaled pattern: da = new double[pat->num]; for (i=0; i<pat->num; ++i) { da[i] = fabs(pat->pattern[i] * styleFactor) / getRadius(); } double tot=0.0; i=0; bool done = false; double curA = a1; //double cx = getCenter().x * factor.x + offsetX; //double cy = - a->getCenter().y * factor.y + getHeight() - offsetY; RS_Vector cp = view->toGui(getCenter()); double r = getRadius() * view->getFactor().x; do { if (pat->pattern[i] > 0.0) { if (tot+da[i]<length) { painter->drawArc(cp, r, curA, curA + da[i], false); } else { painter->drawArc(cp, r, curA, a2, false); } } curA+=da[i]; tot+=da[i]; done=tot>length; i++; if (i>=pat->num) { i=0; } } while(!done); delete[] da; } }
void Plugin_Entity::updateData(QHash<int, QVariant> *data){ if (entity == NULL) return; QHash<int, QVariant> hash = *data; QString str; RS_Vector vec; RS_Pen epen = entity->getPen(); // double num; if (hash.contains(DPI::LAYER)) { str = (hash.take(DPI::LAYER)).toString(); entity->setLayer(str); } if (hash.contains(DPI::LTYPE)) { str = (hash.take(DPI::LTYPE)).toString(); epen.setLineType( Converter.str2lt(str) ); } if (hash.contains(DPI::LWIDTH)) { str = (hash.take(DPI::LWIDTH)).toString(); epen.setWidth( Converter.str2lw(str) ); } if (hash.contains(DPI::COLOR)) { QColor color = hash.take(DPI::COLOR).value<QColor>(); epen.setColor(color); } entity->setPen(epen); RS2::EntityType et = entity->rtti(); switch (et) { //atomicEntity case RS2::EntityLine: { vec = static_cast<RS_Line*>(entity)->getStartpoint(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } static_cast<RS_Line*>(entity)->setStartpoint(vec); vec = static_cast<RS_Line*>(entity)->getEndpoint(); if (hash.contains(DPI::ENDX)) { vec.x = (hash.take(DPI::ENDX)).toDouble(); } if (hash.contains(DPI::ENDY)) { vec.y = (hash.take(DPI::ENDY)).toDouble(); } static_cast<RS_Line*>(entity)->setEndpoint(vec); break;} case RS2::EntityPoint: { vec = static_cast<RS_Point*>(entity)->getPos(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } static_cast<RS_Point*>(entity)->setPos(vec); break; } case RS2::EntityArc: { RS_Arc *arc = static_cast<RS_Arc*>(entity); vec = arc->getCenter(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } arc->setCenter(vec); if (hash.contains(DPI::RADIUS)) { arc->setRadius( (hash.take(DPI::RADIUS)).toDouble() ); } if (hash.contains(DPI::STARTANGLE)) { arc->setAngle1( (hash.take(DPI::STARTANGLE)).toDouble() ); vec.y = (hash.take(DPI::STARTANGLE)).toDouble(); } if (hash.contains(DPI::ENDANGLE)) { arc->setAngle2( (hash.take(DPI::ENDANGLE)).toDouble() ); } break;} case RS2::EntityCircle: { RS_Circle *cir = static_cast<RS_Circle*>(entity); vec = cir->getCenter(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } cir->setCenter(vec); if (hash.contains(DPI::RADIUS)) { cir->setRadius( (hash.take(DPI::RADIUS)).toDouble() ); } break;} case RS2::EntityEllipse: { RS_Ellipse *ellipse = static_cast<RS_Ellipse*>(entity); vec = ellipse->getCenter(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } ellipse->setCenter(vec); vec = ellipse->getMajorP(); if (hash.contains(DPI::ENDX)) { vec.x = (hash.take(DPI::ENDX)).toDouble(); } if (hash.contains(DPI::ENDY)) { vec.y = (hash.take(DPI::ENDY)).toDouble(); } ellipse->setMajorP(vec); if (hash.contains(DPI::STARTANGLE)) { ellipse->setAngle1((hash.take(DPI::STARTANGLE)).toDouble()); } if (hash.contains(DPI::ENDANGLE)) { ellipse->setAngle2((hash.take(DPI::ENDANGLE)).toDouble()); } if (hash.contains(DPI::HEIGHT)) { ellipse->setRatio((hash.take(DPI::HEIGHT)).toDouble()); } if (hash.contains(DPI::REVERSED)) { ellipse->setReversed( (hash.take(DPI::REVERSED)).toBool()); } break;} case RS2::EntitySolid: //TODO //Only used in dimensions ? break; case RS2::EntityConstructionLine: //Unused ? break; case RS2::EntityImage: { break;} case RS2::EntityOverlayBox: //Unused ? break; //EntityContainer case RS2::EntityInsert: { break;} case RS2::EntityText: { RS_Text *txt = static_cast<RS_Text*>(entity); bool move = false; vec = txt->getInsertionPoint(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble() - vec.x; move = true; } else vec.x = 0; if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble() - vec.y; move = true; } else vec.y = 0; if (move) txt->move(vec); if (hash.contains(DPI::TEXTCONTENT)) { txt->setText( (hash.take(DPI::TEXTCONTENT)).toString() ); } if (hash.contains(DPI::STARTANGLE)) { txt->setAngle( (hash.take(DPI::STARTANGLE)).toDouble() ); } if (hash.contains(DPI::HEIGHT)) { txt->setHeight( (hash.take(DPI::HEIGHT)).toDouble() ); } break;} case RS2::EntityHatch: break; case RS2::EntitySpline: break; case RS2::EntityPolyline: { RS_Polyline *pl = static_cast<RS_Polyline*>(entity); if (hash.take(DPI::CLOSEPOLY).toBool()) { pl->setClosed(true); }else{ pl->setClosed(false); } break;} case RS2::EntityVertex: break; case RS2::EntityDimAligned: break; case RS2::EntityDimLinear: break; case RS2::EntityDimRadial: break; case RS2::EntityDimDiametric: break; case RS2::EntityDimAngular: break; case RS2::EntityDimLeader: break; case RS2::EntityUnknown: default: break; } entity->update(); }
void RS_Ellipse::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) { // std::cout<<"RS_Ellipse::draw(): begin\n"; if (painter==NULL || view==NULL) { return; } //visible in grahic view if(isVisibleInWindow(view)==false) return; double ra(getMajorRadius()*view->getFactor().x); double rb(getRatio()*ra); if(rb<RS_TOLERANCE) {//ellipse too small painter->drawLine(view->toGui(minV),view->toGui(maxV)); return; } double mAngle=getAngle(); RS_Vector cp(view->toGui(getCenter())); if ( !isSelected() && ( getPen().getLineType()==RS2::SolidLine || view->getDrawingMode()==RS2::ModePreview)) { painter->drawEllipse(cp, ra, rb, mAngle, getAngle1(), getAngle2(), isReversed()); return; } // Pattern: RS_LineTypePattern* pat; if (isSelected()) { pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { RS_DEBUG->print(RS_Debug::D_WARNING, "Invalid pattern for Ellipse"); return; } // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); double a1(RS_Math::correctAngle(getAngle1())); double a2(RS_Math::correctAngle(getAngle2())); if (isReversed()) std::swap(a1,a2); if(a2 <a1+RS_TOLERANCE_ANGLE) a2 +=2.*M_PI; painter->setPen(pen); int i(0),j(0); double* ds = new double[pat->num>0?pat->num:0]; if(pat->num>0){ while( i<pat->num){ ds[i]=pat->pattern[i] ;//pattern length i++; } j=i; }else { delete[] ds; RS_DEBUG->print(RS_Debug::D_WARNING,"Invalid pattern when drawing ellipse"); painter->drawEllipse(cp, ra, rb, mAngle, a1, a2, false); return; } double tot=0.0; double curA(a1); double da,a3; bool notDone(true); for(i=0;notDone;i=(i+1)%j) {//draw patterned ellipse a3 = curA + fabs(ds[i])/RS_Vector(ra*sin(curA),rb*cos(curA)).magnitude(); if(a3>a2){ a3=a2; notDone=false; } tot += da; if (ds[i]>0.){ painter->drawEllipse(cp, ra, rb, mAngle, curA, a3, false); } curA=a3; } delete[] ds; }
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) { if (painter==NULL || view==NULL) { return; } //only draw the visible portion of line QVector<RS_Vector> endPoints(0); RS_Vector vpMin(view->toGraph(0,view->getHeight())); RS_Vector vpMax(view->toGraph(view->getWidth(),0)); QPolygonF visualBox(QRectF(vpMin.x,vpMin.y,vpMax.x-vpMin.x, vpMax.y-vpMin.y)); if( getStartpoint().isInWindowOrdered(vpMin, vpMax) ) endPoints<<getStartpoint(); if( getEndpoint().isInWindowOrdered(vpMin, vpMax) ) endPoints<<getEndpoint(); if(endPoints.size()<2){ QVector<RS_Vector> vertex; for(unsigned short i=0;i<4;i++){ const QPointF& vp(visualBox.at(i)); vertex<<RS_Vector(vp.x(),vp.y()); } for(unsigned short i=0;i<4;i++){ RS_Line line(NULL,RS_LineData(vertex.at(i),vertex.at((i+1)%4))); auto&& vpIts=RS_Information::getIntersection(static_cast<RS_Entity*>(this), &line, true); if( vpIts.size()==0) continue; endPoints<<vpIts.get(0); } } if(endPoints.size()<2) return; if( (endPoints[0] - getStartpoint()).squared() > (endPoints[1] - getStartpoint()).squared() ) std::swap(endPoints[0],endPoints[1]); RS_Vector pStart(view->toGui(endPoints.at(0))); RS_Vector pEnd(view->toGui(endPoints.at(1))); // std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl; RS_Vector direction=pEnd-pStart; if(isHelpLayer(true) && direction.squared() > RS_TOLERANCE){ //extend line on a help layer to fill the whole view RS_Vector lb(0,0); RS_Vector rt(view->getWidth(),view->getHeight()); QList<RS_Vector> rect; rect<<lb<<RS_Vector(rt.x,lb.y); rect<<rt<<RS_Vector(lb.x,rt.y); rect<<lb; RS_VectorSolutions sol; RS_Line dLine(pStart,pEnd); for(int i=0;i<4;i++){ RS_Line bLine(rect.at(i),rect.at(i+1)); RS_VectorSolutions sol2=RS_Information::getIntersection(&bLine, &dLine); if( sol2.getNumber()>0 && bLine.isPointOnEntity(sol2.get(0),RS_TOLERANCE)) { sol.push_back(sol2.get(0)); } } switch(sol.getNumber()){ case 2: pStart=sol.get(0); pEnd=sol.get(1); break; case 3: case 4: pStart=sol.get(0); pEnd=sol.get(2); break; default: return; } direction=pEnd-pStart; } double length=direction.magnitude(); patternOffset -= length; if (( !isSelected() && ( getPen().getLineType()==RS2::SolidLine || view->getDrawingMode()==RS2::ModePreview)) ) { //if length is too small, attempt to draw the line, could be a potential bug painter->drawLine(pStart,pEnd); return; } // double styleFactor = getStyleFactor(view); // Pattern: RS_LineTypePattern* pat; if (isSelected()) { // styleFactor=1.; pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { // patternOffset -= length; RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Line::draw: Invalid line pattern"); painter->drawLine(pStart,pEnd); return; } // patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength; if(length<=RS_TOLERANCE){ painter->drawLine(pStart,pEnd); return; //avoid division by zero } direction/=length; //cos(angle), sin(angle) // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); // index counter int i; // pattern segment length: double patternSegmentLength = pat->totalLength; // create pattern: RS_Vector* dp=new RS_Vector[pat->num > 0?pat->num:0]; double* ds=new double[pat->num > 0?pat->num:0]; if (pat->num >0 ){ double dpmm=static_cast<RS_PainterQt*>(painter)->getDpmm(); for (i=0; i<pat->num; ++i) { // ds[j]=pat->pattern[i] * styleFactor; //fixme, styleFactor support needed ds[i]=dpmm*pat->pattern[i]; if( fabs(ds[i]) < 1. ) ds[i] = (ds[i]>=0.)?1.:-1.; dp[i] = direction*fabs(ds[i]); } }else { delete[] dp; delete[] ds; RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread"); painter->drawLine(view->toGui(getStartpoint()), view->toGui(getEndpoint())); return; } double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength; // double total= patternOffset-patternSegmentLength; RS_Vector p1,p2,p3; RS_Vector curP(pStart+direction*total); double t2; for(int j=0;total<length;j=(j+1)%i) { // line segment (otherwise space segment) t2=total+fabs(ds[j]); p3=curP+dp[j]; if (ds[j]>0.0 && t2 > 0.0) { // drop the whole pattern segment line, for ds[i]<0: // trim end points of pattern segment line to line p1 =(total > -0.5)? curP:pStart; p2 =(t2<length+0.5)?p3:pEnd; painter->drawLine(p1,p2); } total=t2; curP=p3; } delete[] dp; delete[] ds; }
/** directly draw the arc, assuming the whole arc is within visible window */ void RS_Arc::drawVisible(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) { if (painter==NULL || view==NULL) { return; } //visible in grahic view if(isVisibleInWindow(view)==false) return; RS_Vector cp=view->toGui(getCenter()); double ra=getRadius()*view->getFactor().x; double length=getLength()*view->getFactor().x; //double styleFactor = getStyleFactor(); patternOffset -= length; // simple style-less lines if ( !isSelected() && ( getPen().getLineType()==RS2::SolidLine || view->getDrawingMode()==RS2::ModePreview)) { painter->drawArc(cp, ra, getAngle1(), getAngle2(), isReversed()); return; } // double styleFactor = getStyleFactor(view); // if (styleFactor<0.0) { // painter->drawArc(cp, // ra, // getAngle1(), getAngle2(), // isReversed()); // return; // } // Pattern: const RS_LineTypePattern* pat; if (isSelected()) { pat = &RS_LineTypePattern::patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL|| ra<0.5) {//avoid division by zero from small ra RS_DEBUG->print("%s: Invalid line pattern or radius too small, drawing arc using solid line", __func__); painter->drawArc(cp, ra, getAngle1(),getAngle2(), isReversed()); return; } // patternOffset=remainder(patternOffset - length -0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength; if (ra<RS_TOLERANCE_ANGLE){ return; } // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); // create scaled pattern: std::vector<double> da(0); double patternSegmentLength(pat->totalLength); double ira=1./ra; size_t i(0); // index counter if(pat->num>0) { double dpmm=static_cast<RS_PainterQt*>(painter)->getDpmm(); da.resize(pat->num); while(i<pat->num){ // da[j] = pat->pattern[i++] * styleFactor; //fixme, stylefactor needed da[i] =dpmm*(isReversed()? -fabs(pat->pattern[i]):fabs(pat->pattern[i])); if( fabs(da[i]) < 1. ) da[i] = (da[i]>=0.)?1.:-1.; da[i] *= ira; i++; } }else { //invalid pattern RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Arc::draw(): invalid line pattern\n"); painter->drawArc(cp, ra, getAngle1(), getAngle2(), isReversed()); return; } // bool done = false; double total=remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength)-0.5*patternSegmentLength; double a1(RS_Math::correctAngle(getAngle1())); double a2(RS_Math::correctAngle(getAngle2())); if(isReversed()) {//always draw from a1 to a2, so, patternOffset is is automatic if(a1<a2+RS_TOLERANCE_ANGLE) a2 -= 2.*M_PI; total = a1 - total*ira; //in angle }else{ if(a2<a1+RS_TOLERANCE_ANGLE) a2 += 2.*M_PI; total = a1 + total*ira; //in angle } double limit(fabs(a1-a2)); double t2; double a11,a21; for(int j=0; fabs(total-a1)<limit ;j=(j+1)%i) { t2=total+da[j]; if(pat->pattern[j]>0.0) { if (fabs(t2-a2)<limit) { a11=(fabs(total-a2)<limit)?total:a1; a21=(fabs(t2-a1)<limit)?t2:a2; painter->drawArc(cp, ra, a11, a21, isReversed()); } } total=t2; } }
void RS_Ellipse::draw(RS_Painter* painter, RS_GraphicView* view, double patternOffset) { if (painter==NULL || view==NULL) { return; } if (getPen().getLineType()==RS2::SolidLine || isSelected() || view->getDrawingMode()==RS2::ModePreview) { painter->drawEllipse(view->toGui(getCenter()), getMajorRadius() * view->getFactor().x, getMinorRadius() * view->getFactor().x, getAngle(), getAngle1(), getAngle2(), isReversed()); } else { double styleFactor = getStyleFactor(view); if (styleFactor<0.0) { painter->drawEllipse(view->toGui(getCenter()), getMajorRadius() * view->getFactor().x, getMinorRadius() * view->getFactor().x, getAngle(), getAngle1(), getAngle2(), isReversed()); return; } // Pattern: RS_LineTypePattern* pat; if (isSelected()) { pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { return; } // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); double* da; // array of distances in x. int i; // index counter double length = getAngleLength(); // create pattern: da = new double[pat->num]; double tot=0.0; i=0; bool done = false; double curA = getAngle1(); double curR; RS_Vector cp = view->toGui(getCenter()); double r1 = getMajorRadius() * view->getFactor().x; double r2 = getMinorRadius() * view->getFactor().x; do { curR = sqrt(RS_Math::pow(getMinorRadius()*cos(curA), 2.0) + RS_Math::pow(getMajorRadius()*sin(curA), 2.0)); if (curR>1.0e-6) { da[i] = fabs(pat->pattern[i] * styleFactor) / curR; if (pat->pattern[i] * styleFactor > 0.0) { if (tot+fabs(da[i])<length) { painter->drawEllipse(cp, r1, r2, getAngle(), curA, curA + da[i], false); } else { painter->drawEllipse(cp, r1, r2, getAngle(), curA, getAngle2(), false); } } } curA+=da[i]; tot+=fabs(da[i]); done=tot>length; i++; if (i>=pat->num) { i=0; } } while(!done); delete[] da; } }
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) { if (painter==NULL || view==NULL) { return; } //visible in grahic view if(isVisibleInWindow(view)==false) return; RS_Vector pStart(view->toGui(getStartpoint())); RS_Vector pEnd(view->toGui(getEndpoint())); // std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl; RS_Vector direction=pEnd-pStart; if(isHelpLayer(true) && direction.squared() > RS_TOLERANCE){ //extend line on a help layer to fill the whole view RS_Vector lb(0,0); RS_Vector rt(view->getWidth(),view->getHeight()); QList<RS_Vector> rect; rect<<lb<<RS_Vector(rt.x,lb.y); rect<<rt<<RS_Vector(lb.x,rt.y); rect<<lb; RS_VectorSolutions sol; RS_Line dLine(pStart,pEnd); for(int i=0;i<4;i++){ RS_Line bLine(rect.at(i),rect.at(i+1)); RS_VectorSolutions sol2=RS_Information::getIntersection(&bLine, &dLine); if( sol2.getNumber()>0 && bLine.isPointOnEntity(sol2.get(0),RS_TOLERANCE)) { sol.push_back(sol2.get(0)); } } switch(sol.getNumber()){ case 2: pStart=sol.get(0); pEnd=sol.get(1); break; case 3: case 4: pStart=sol.get(0); pEnd=sol.get(2); break; default: return; } direction=pEnd-pStart; } double length=direction.magnitude(); patternOffset -= length; if (( !isSelected() && ( getPen().getLineType()==RS2::SolidLine || view->getDrawingMode()==RS2::ModePreview)) ) { //if length is too small, attempt to draw the line, could be a potential bug painter->drawLine(pStart,pEnd); return; } // double styleFactor = getStyleFactor(view); // Pattern: RS_LineTypePattern* pat; if (isSelected()) { // styleFactor=1.; pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { // patternOffset -= length; RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Line::draw: Invalid line pattern"); painter->drawLine(pStart,pEnd); return; } // patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength; if(length<=RS_TOLERANCE){ painter->drawLine(pStart,pEnd); return; //avoid division by zero } direction/=length; //cos(angle), sin(angle) // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); // index counter int i; // pattern segment length: double patternSegmentLength = pat->totalLength; // create pattern: RS_Vector* dp=new RS_Vector[pat->num > 0?pat->num:0]; double* ds=new double[pat->num > 0?pat->num:0]; if (pat->num >0 ){ for (i=0; i<pat->num; ++i) { // ds[j]=pat->pattern[i] * styleFactor; //fixme, styleFactor support needed ds[i]=pat->pattern[i] ; dp[i] = direction*fabs(ds[i]); } }else { delete[] dp; delete[] ds; RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread"); painter->drawLine(view->toGui(getStartpoint()), view->toGui(getEndpoint())); return; } double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength; // double total= patternOffset-patternSegmentLength; RS_Vector p1,p2,p3; RS_Vector curP(pStart+direction*total); double t2; for(int j=0;total<length;j=(j+1)%i) { // line segment (otherwise space segment) t2=total+fabs(ds[j]); p3=curP+dp[j]; if (ds[j]>0.0 && t2 > 0.0) { // drop the whole pattern segment line, for ds[i]<0: // trim end points of pattern segment line to line p1 =(total > -0.5)? curP:pStart; p2 =(t2<length+0.5)?p3:pEnd; painter->drawLine(p1,p2); } total=t2; curP=p3; } delete[] dp; delete[] ds; }
void RS_Circle::draw(RS_Painter* painter, RS_GraphicView* view, double& /*patternOffset*/) { if (painter==NULL || view==NULL) { return; } RS_Vector cp(view->toGui(getCenter())); double ra(fabs(getRadius()*view->getFactor().x)); //double styleFactor = getStyleFactor(); // simple style-less lines if ( !isSelected() && ( getPen().getLineType()==RS2::SolidLine || view->getDrawingMode()==RS2::ModePreview)) { painter->drawArc(cp, ra, 0.0, 2*M_PI, false); return; } // double styleFactor = getStyleFactor(view); // if (styleFactor<0.0) { // painter->drawArc(cp, // ra, // 0.0, 2*M_PI, // false); // return; // } // Pattern: RS_LineTypePattern* pat; if (isSelected()) { pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { return; } if (ra<1.){ painter->drawArc(cp, ra, 0.0, 2*M_PI, false); return; } // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); // create pattern: double* da=new double[pat->num>0?pat->num:0]; int i(0),j(0); // index counter if(pat->num>0){ while(i<pat->num){ // da[j] = pat->pattern[i++] * styleFactor; //fixme, styleFactor needed da[i] = pat->pattern[i]/ra ; i++; } j=i; }else { //invalid pattern delete[] da; painter->drawArc(cp, ra, 0.,2.*M_PI, false); return; } double curA ( 0.0); double a2; bool notDone=true; for(i=0;notDone;i=(i+1)%j) { a2= curA+fabs(da[i]); if(a2>2.*M_PI) { a2=2.*M_PI; notDone=false; } if (da[i]>0.){ painter->drawArc(cp, ra, curA, a2, false); } curA=a2; } delete[] da; }
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double patternOffset) { if (painter==NULL || view==NULL) { return; } if (getPen().getLineType()==RS2::SolidLine || isSelected() || view->getDrawingMode()==RS2::ModePreview) { painter->drawLine(view->toGui(getStartpoint()), view->toGui(getEndpoint())); } else { double styleFactor = getStyleFactor(view); if (styleFactor<0.0) { painter->drawLine(view->toGui(getStartpoint()), view->toGui(getEndpoint())); return; } // Pattern: RS_LineTypePattern* pat; if (isSelected()) { pat = &patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (pat==NULL) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Line::draw: Invalid line pattern"); return; } // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); // index counter int i; // line data: double length = getLength(); double angle = getAngle1(); // pattern segment length: double patternSegmentLength = 0.0; // create pattern: RS_Vector* dp = new RS_Vector[pat->num]; for (i=0; i<pat->num; ++i) { dp[i] = RS_Vector(cos(angle) * fabs(pat->pattern[i] * styleFactor), sin(angle) * fabs(pat->pattern[i] * styleFactor)); patternSegmentLength += fabs(pat->pattern[i] * styleFactor); } // handle pattern offset: int m; if (patternOffset<0.0) { m = (int)ceil(patternOffset / patternSegmentLength); } else { m = (int)floor(patternOffset / patternSegmentLength); } patternOffset -= (m*patternSegmentLength); //if (patternOffset<0.0) { // patternOffset+=patternSegmentLength; //} //RS_DEBUG->print("pattern. offset: %f", patternOffset); RS_Vector patternOffsetVec; patternOffsetVec.setPolar(patternOffset, angle); double tot=patternOffset; i=0; bool done = false; bool cutStartpoint, cutEndpoint, drop; RS_Vector curP=getStartpoint()+patternOffsetVec; do { cutStartpoint = false; cutEndpoint = false; drop = false; // line segment (otherwise space segment) if (pat->pattern[i]>0.0) { // drop the whole pattern segment line: if (tot+pat->pattern[i]*styleFactor < 0.0) { drop = true; } else { // trim startpoint of pattern segment line to line startpoint if (tot < 0.0) { cutStartpoint = true; } // trim endpoint of pattern segment line to line endpoint if (tot+pat->pattern[i]*styleFactor > length) { cutEndpoint = true; } } if (drop) { // do nothing } else { RS_Vector p1 = curP; RS_Vector p2 = curP + dp[i]; if (cutStartpoint) { p1 = getStartpoint(); } if (cutEndpoint) { p2 = getEndpoint(); } painter->drawLine(view->toGui(p1), view->toGui(p2)); } } curP+=dp[i]; tot+=fabs(pat->pattern[i]*styleFactor); //RS_DEBUG->print("pattern. tot: %f", tot); done=tot>length; i++; if (i>=pat->num) { i=0; } } while(!done); delete[] dp; } }
void RS_Line::draw(RS_Painter* painter, RS_GraphicView* view, double& patternOffset) { if (! (painter && view)) { return; } //only draw the visible portion of line LC_Rect const viewportRect{view->toGraph(0, 0), view->toGraph(view->getWidth(), view->getHeight())}; RS_VectorSolutions endPoints(0); if (viewportRect.inArea(getStartpoint(), RS_TOLERANCE)) endPoints.push_back(getStartpoint()); if (viewportRect.inArea(getEndpoint(), RS_TOLERANCE)) endPoints.push_back(getEndpoint()); RS_EntityContainer ec(nullptr); ec.addRectangle(viewportRect.minP(), viewportRect.maxP()); if (endPoints.size()<2){ RS_VectorSolutions vpIts; for(auto p: ec) { auto const sol=RS_Information::getIntersection(this, p, true); for (auto const& vp: sol) { if (vpIts.getClosestDistance(vp) <= RS_TOLERANCE * 10.) continue; vpIts.push_back(vp); } } for (auto const& vp: vpIts) { if (endPoints.getClosestDistance(vp) <= RS_TOLERANCE * 10.) continue; endPoints.push_back(vp); } } if (endPoints.size()<2) return; if ((endPoints[0] - getStartpoint()).squared() > (endPoints[1] - getStartpoint()).squared() ) std::swap(endPoints[0],endPoints[1]); RS_Vector pStart{view->toGui(endPoints.at(0))}; RS_Vector pEnd{view->toGui(endPoints.at(1))}; // std::cout<<"draw line: "<<pStart<<" to "<<pEnd<<std::endl; RS_Vector direction = pEnd-pStart; if (isConstruction(true) && direction.squared() > RS_TOLERANCE){ //extend line on a construction layer to fill the whole view RS_VectorSolutions vpIts; for(auto p: ec) { auto const sol=RS_Information::getIntersection(this, p, false); for (auto const& vp: sol) { if (vpIts.getClosestDistance(vp) <= RS_TOLERANCE * 10.) continue; vpIts.push_back(vp); } } //draw construction lines up to viewport border switch (vpIts.size()) { case 2: // no need to sort intersections break; case 3: case 4: { // will use the inner two points size_t i{0}; for (size_t j = 2; j < vpIts.size(); ++j) { if (viewportRect.inArea(vpIts.at(j), RS_TOLERANCE * 10.)) std::swap(vpIts[j], vpIts[i++]); } } break; default: //should not happen return; } pStart=view->toGui(vpIts.get(0)); pEnd=view->toGui(vpIts.get(1)); direction=pEnd-pStart; } double length=direction.magnitude(); patternOffset -= length; if (( !isSelected() && ( getPen().getLineType()==RS2::SolidLine || view->getDrawingMode()==RS2::ModePreview)) ) { //if length is too small, attempt to draw the line, could be a potential bug painter->drawLine(pStart,pEnd); return; } // double styleFactor = getStyleFactor(view); // Pattern: const RS_LineTypePattern* pat; if (isSelected()) { // styleFactor=1.; pat = &RS_LineTypePattern::patternSelected; } else { pat = view->getPattern(getPen().getLineType()); } if (!pat) { // patternOffset -= length; RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Line::draw: Invalid line pattern"); painter->drawLine(pStart,pEnd); return; } // patternOffset = remainder(patternOffset - length-0.5*pat->totalLength,pat->totalLength)+0.5*pat->totalLength; if(length<=RS_TOLERANCE){ painter->drawLine(pStart,pEnd); return; //avoid division by zero } direction/=length; //cos(angle), sin(angle) // Pen to draw pattern is always solid: RS_Pen pen = painter->getPen(); pen.setLineType(RS2::SolidLine); painter->setPen(pen); // index counter size_t i; // pattern segment length: double patternSegmentLength = pat->totalLength; // create pattern: size_t const patnum=pat->num > 0?pat->num:0; std::vector<RS_Vector> dp(patnum); std::vector<double> ds(patnum, 0.); if (pat->num >0 ){ double dpmm=static_cast<RS_PainterQt*>(painter)->getDpmm(); for (i=0; i<pat->num; ++i) { // ds[j]=pat->pattern[i] * styleFactor; //fixme, styleFactor support needed ds[i]=dpmm*pat->pattern[i]; if (fabs(ds[i]) < 1. ) ds[i] = (ds[i]>=0.)?1.:-1.; dp[i] = direction*fabs(ds[i]); } } else { RS_DEBUG->print(RS_Debug::D_WARNING,"invalid line pattern for line, draw solid line instread"); painter->drawLine(view->toGui(getStartpoint()), view->toGui(getEndpoint())); return; } double total= remainder(patternOffset-0.5*patternSegmentLength,patternSegmentLength) -0.5*patternSegmentLength; // double total= patternOffset-patternSegmentLength; RS_Vector curP{pStart+direction*total}; for (int j=0; total<length; j=(j+1)%i) { // line segment (otherwise space segment) double const t2=total+fabs(ds[j]); RS_Vector const& p3=curP+dp[j]; if (ds[j]>0.0 && t2 > 0.0) { // drop the whole pattern segment line, for ds[i]<0: // trim end points of pattern segment line to line RS_Vector const& p1 =(total > -0.5)?curP:pStart; RS_Vector const& p2 =(t2<length+0.5)?p3:pEnd; painter->drawLine(p1,p2); } total=t2; curP=p3; } }
/** * Updates the entity buffer of this insert entity. This method * needs to be called whenever the block this insert is based on changes. */ void RS_Insert::update() { RS_DEBUG->print("RS_Insert::update"); RS_DEBUG->print("RS_Insert::update: name: %s", data.name.toLatin1().data()); // RS_DEBUG->print("RS_Insert::update: insertionPoint: %f/%f", // data.insertionPoint.x, data.insertionPoint.y); if (updateEnabled==false) { return; } clear(); RS_Block* blk = getBlockForInsert(); if (blk==nullptr) { //return nullptr; RS_DEBUG->print("RS_Insert::update: Block is nullptr"); return; } if (isUndone()) { RS_DEBUG->print("RS_Insert::update: Insert is in undo list"); return; } if (fabs(data.scaleFactor.x)<1.0e-6 || fabs(data.scaleFactor.y)<1.0e-6) { RS_DEBUG->print("RS_Insert::update: scale factor is 0"); return; } RS_Pen tmpPen; /*QListIterator<RS_Entity> it = createIterator(); RS_Entity* e; while ( (e = it.current()) != nullptr ) { ++it;*/ RS_DEBUG->print("RS_Insert::update: cols: %d, rows: %d", data.cols, data.rows); RS_DEBUG->print("RS_Insert::update: block has %d entities", blk->count()); //int i_en_counts=0; for(auto e: *blk){ for (int c=0; c<data.cols; ++c) { // RS_DEBUG->print("RS_Insert::update: col %d", c); for (int r=0; r<data.rows; ++r) { // i_en_counts++; // RS_DEBUG->print("RS_Insert::update: row %d", r); if (e->rtti()==RS2::EntityInsert && data.updateMode!=RS2::PreviewUpdate) { // RS_DEBUG->print("RS_Insert::update: updating sub-insert"); ((RS_Insert*)e)->update(); } // RS_DEBUG->print("RS_Insert::update: cloning entity"); RS_Entity* ne; if ( (data.scaleFactor.x - data.scaleFactor.y)>1.0e-6) { if (e->rtti()== RS2::EntityArc) { RS_Arc* a= (RS_Arc*)e; ne = new RS_Ellipse(this, RS_EllipseData(a->getCenter(), RS_Vector(a->getRadius(), 0), 1, a->getAngle1(), a->getAngle2(), a->isReversed() )); ne->setLayer(e->getLayer()); ne->setPen(e->getPen(false)); } else if (e->rtti()== RS2::EntityCircle) { RS_Circle* a= (RS_Circle*)e; ne = new RS_Ellipse(this, RS_EllipseData(a->getCenter(), RS_Vector(a->getRadius(), 0), 1, 0.0,2.0*M_PI, false)); ne->setLayer(e->getLayer()); ne->setPen(e->getPen(false)); } else ne = e->clone(); } else ne = e->clone(); ne->initId(); ne->setUpdateEnabled(false); // if entity layer are 0 set to insert layer to allow "1 layer control" bug ID #3602152 RS_Layer *l= ne->getLayer();//special fontchar block don't have if (l != nullptr && ne->getLayer()->getName() == "0") ne->setLayer(this->getLayer()); ne->setParent(this); ne->setVisible(getFlag(RS2::FlagVisible)); // RS_DEBUG->print("RS_Insert::update: transforming entity"); // Move: // RS_DEBUG->print("RS_Insert::update: move 1"); if (fabs(data.scaleFactor.x)>1.0e-6 && fabs(data.scaleFactor.y)>1.0e-6) { ne->move(data.insertionPoint + RS_Vector(data.spacing.x/data.scaleFactor.x*c, data.spacing.y/data.scaleFactor.y*r)); } else { ne->move(data.insertionPoint); } // Move because of block base point: // RS_DEBUG->print("RS_Insert::update: move 2"); ne->move(blk->getBasePoint()*-1); // Scale: // RS_DEBUG->print("RS_Insert::update: scale"); ne->scale(data.insertionPoint, data.scaleFactor); // Rotate: // RS_DEBUG->print("RS_Insert::update: rotate"); ne->rotate(data.insertionPoint, data.angle); // Select: ne->setSelected(isSelected()); // individual entities can be on indiv. layers tmpPen = ne->getPen(false); // color from block (free floating): if (tmpPen.getColor()==RS_Color(RS2::FlagByBlock)) { tmpPen.setColor(getPen().getColor()); } // line width from block (free floating): if (tmpPen.getWidth()==RS2::WidthByBlock) { tmpPen.setWidth(getPen().getWidth()); } // line type from block (free floating): if (tmpPen.getLineType()==RS2::LineByBlock) { tmpPen.setLineType(getPen().getLineType()); } // now that we've evaluated all flags, let's strip them: // TODO: strip all flags (width, line type) //tmpPen.setColor(tmpPen.getColor().stripFlags()); ne->setPen(tmpPen); ne->setUpdateEnabled(true); if (data.updateMode!=RS2::PreviewUpdate) { // RS_DEBUG->print("RS_Insert::update: updating new entity"); ne->update(); } // RS_DEBUG->print("RS_Insert::update: adding new entity"); appendEntity(ne); // std::cout<<"done # of entity: "<<i_en_counts<<std::endl; } } } calculateBorders(); RS_DEBUG->print("RS_Insert::update: OK"); }
/** * Updates the entity buffer of this insert entity. This method * needs to be called whenever the block this insert is based on changes. */ void RS_Insert::update() { RS_DEBUG->print("RS_Insert::update"); RS_DEBUG->print("RS_Insert::update: name: %s", data.name.latin1()); RS_DEBUG->print("RS_Insert::update: insertionPoint: %f/%f", data.insertionPoint.x, data.insertionPoint.y); if (updateEnabled==false) { return; } clear(); RS_Block* blk = getBlockForInsert(); if (blk==NULL) { //return NULL; RS_DEBUG->print("RS_Insert::update: Block is NULL"); return; } if (isUndone()) { RS_DEBUG->print("RS_Insert::update: Insert is in undo list"); return; } if (fabs(data.scaleFactor.x)<1.0e-6 || fabs(data.scaleFactor.y)<1.0e-6) { RS_DEBUG->print("RS_Insert::update: scale factor is 0"); return; } RS_Pen tmpPen; /*RS_PtrListIterator<RS_Entity> it = createIterator(); RS_Entity* e; while ( (e = it.current()) != NULL ) { ++it;*/ RS_DEBUG->print("RS_Insert::update: cols: %d, rows: %d", data.cols, data.rows); RS_DEBUG->print("RS_Insert::update: block has %d entities", blk->count()); for (RS_Entity* e=blk->firstEntity(); e!=NULL; e=blk->nextEntity()) { for (int c=0; c<data.cols; ++c) { RS_DEBUG->print("RS_Insert::update: col %d", c); for (int r=0; r<data.rows; ++r) { RS_DEBUG->print("RS_Insert::update: row %d", r); if (e->rtti()==RS2::EntityInsert && data.updateMode!=RS2::PreviewUpdate) { RS_DEBUG->print("RS_Insert::update: updating sub-insert"); ((RS_Insert*)e)->update(); } RS_DEBUG->print("RS_Insert::update: cloning entity"); RS_Entity* ne = e->clone(); ne->initId(); ne->setUpdateEnabled(false); ne->setParent(this); ne->setVisible(getFlag(RS2::FlagVisible)); RS_DEBUG->print("RS_Insert::update: transforming entity"); // Move: RS_DEBUG->print("RS_Insert::update: move 1"); if (fabs(data.scaleFactor.x)>1.0e-6 && fabs(data.scaleFactor.y)>1.0e-6) { ne->move(data.insertionPoint + RS_Vector(data.spacing.x/data.scaleFactor.x*c, data.spacing.y/data.scaleFactor.y*r)); } else { ne->move(data.insertionPoint); } // Move because of block base point: RS_DEBUG->print("RS_Insert::update: move 2"); ne->move(blk->getBasePoint()*-1); // Scale: RS_DEBUG->print("RS_Insert::update: scale"); ne->scale(data.insertionPoint, data.scaleFactor); // Rotate: RS_DEBUG->print("RS_Insert::update: rotate"); ne->rotate(data.insertionPoint, data.angle); // Select: ne->setSelected(isSelected()); // individual entities can be on indiv. layers tmpPen = ne->getPen(false); // color from block (free floating): if (tmpPen.getColor()==RS_Color(RS2::FlagByBlock)) { tmpPen.setColor(getPen().getColor()); } // line width from block (free floating): if (tmpPen.getWidth()==RS2::WidthByBlock) { tmpPen.setWidth(getPen().getWidth()); } // line type from block (free floating): if (tmpPen.getLineType()==RS2::LineByBlock) { tmpPen.setLineType(getPen().getLineType()); } // now that we've evaluated all flags, let's strip them: // TODO: strip all flags (width, line type) //tmpPen.setColor(tmpPen.getColor().stripFlags()); ne->setPen(tmpPen); ne->setUpdateEnabled(true); if (data.updateMode!=RS2::PreviewUpdate) { RS_DEBUG->print("RS_Insert::update: updating new entity"); ne->update(); } RS_DEBUG->print("RS_Insert::update: adding new entity"); addEntity(ne); } } } calculateBorders(); RS_DEBUG->print("RS_Insert::update: OK"); }
/** * 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(auto se: entities){ view->drawEntity(painter,se); } return; } //area of solid fill. Use polygon approximation, except trivial cases QPainterPath path; QList<QPolygon> paClosed; QPolygon pa; // QPolygon jp; // jump points // loops: if (needOptimization==true) { for(auto l: entities){ if (l->rtti()==RS2::EntityContainer) { RS_EntityContainer* loop = (RS_EntityContainer*)l; loop->optimizeContours(); } } needOptimization = false; } // loops: for(auto l: entities){ l->setLayer(getLayer()); if (l->rtti()==RS2::EntityContainer) { RS_EntityContainer* loop = (RS_EntityContainer*)l; // edges: for(auto e: *loop){ 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; // } if(pa.size() && (pa.last()-pt1).manhattanLength()>=1) pa<<pt1; pa<<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()); if(pa.size() &&pa2.size()&&(pa.last()-pa2.first()).manhattanLength()<1) pa2.remove(0,1); 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() ); // qDebug()<<"ellipse: "<<ellipse->getCenter().x<<","<<ellipse->getCenter().y; // qDebug()<<"ellipse: pa2.size()="<<pa2.size(); // qDebug()<<"ellipse: pa2="<<pa2; if(pa.size() && pa2.size()&&(pa.last()-pa2.first()).manhattanLength()<1) pa2.remove(0,1); 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; } // qDebug()<<"pa="<<pa; if( pa.size()>2 && pa.first() == pa.last()) { paClosed<<pa; pa.clear(); } } } } if(pa.size()>2){ pa<<pa.first(); paClosed<<pa; } for(auto& p:paClosed){ path.addPolygon(p); } //bug#474, restore brush after solid fill const QBrush brush(painter->brush()); const RS_Pen pen=painter->getPen(); painter->setBrush(pen.getColor()); painter->disablePen(); painter->drawPath(path); painter->setBrush(brush); painter->setPen(pen); }
/** * Gets the pen needed to draw this entity. * The attributes can also come from the layer this entity is on * if the flags are set accordingly. * * @param resolve true: Resolve the pen to a drawable pen (e.g. the pen * from the layer or parent..) * false: Don't resolve and return a pen or ByLayer, ByBlock, ... * * @return Pen for this entity. */ RS_Pen RS_Entity::getPen(bool resolve) const { if (!resolve) { return pen; } else { RS_Pen p = pen; RS_Layer* l = getLayer(true); // use parental attributes (e.g. vertex of a polyline, block // entities when they are drawn in block documents): if (parent) { //if pen is invalid gets all from parent if (!p.isValid() ) { p = parent->getPen(); } //pen is valid, verify byBlock parts RS_EntityContainer* ep = parent; //If parent is byblock check parent.parent (nested blocks) while (p.getColor().isByBlock()){ if (ep) { p.setColor(parent->getPen().getColor()); ep = ep->parent; } else break; } ep = parent; while (p.getWidth()==RS2::WidthByBlock){ if (ep) { p.setWidth(parent->getPen().getWidth()); ep = ep->parent; } else break; } ep = parent; while (p.getLineType()==RS2::LineByBlock){ if (ep) { p.setLineType(parent->getPen().getLineType()); ep = ep->parent; } else break; } } // check byLayer attributes: if (l) { // use layer's color: if (p.getColor().isByLayer()) { p.setColor(l->getPen().getColor()); } // use layer's width: if (p.getWidth()==RS2::WidthByLayer) { p.setWidth(l->getPen().getWidth()); } // use layer's linetype: if (p.getLineType()==RS2::LineByLayer) { p.setLineType(l->getPen().getLineType()); } //} } return p; } }
void RS_GraphicView::setPenForEntity(RS_Painter *painter,RS_Entity *e) { if (draftMode) { painter->setPen(RS_Pen(foreground, RS2::Width00, RS2::SolidLine)); } // Getting pen from entity (or layer) RS_Pen pen = e->getPen(true); int w = pen.getWidth(); if (w<0) { w = 0; } #if 1 /*TRUE*/ // - Scale pen width. // - Notes: pen width is not scaled on print and print preview. // This is the standard (AutoCAD like) behaviour. // bug# 3437941 // ------------------------------------------------------------ if (!draftMode) { double uf = 1.0; // Unit factor. double wf = 1.0; // Width factor. RS_Graphic* graphic = container->getGraphic(); if (graphic) { uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit()); if ( (isPrinting() || isPrintPreview()) && graphic->getPaperScale() > RS_TOLERANCE ) { wf = 1.0 / graphic->getPaperScale(); } } pen.setScreenWidth(toGuiDX(w / 100.0 * uf * wf)); } else { // pen.setWidth(RS2::Width00); pen.setScreenWidth(0); } #else // - Scale pen width. // - Notes: pen width is scaled on print and print preview. // This is not the standard (AutoCAD like) behaviour. // -------------------------------------------------------- if (!draftMode) { double uf = 1.0; // Unit factor. RS_Graphic* graphic = container->getGraphic(); if (graphic) uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit()); pen.setScreenWidth(toGuiDX(w / 100.0 * uf)); } else pen.setScreenWidth(0); #endif // prevent drawing with 1-width which is slow: if (RS_Math::round(pen.getScreenWidth())==1) { pen.setScreenWidth(0.0); } // prevent background color on background drawing: if (pen.getColor().stripFlags()==background.stripFlags()) { pen.setColor(foreground); } // this entity is selected: if (e->isSelected()) { pen.setLineType(RS2::DotLine); pen.setColor(selectedColor); } // this entity is highlighted: if (e->isHighlighted()) { pen.setColor(highlightedColor); } // deleting not drawing: if (getDeleteMode()) { pen.setColor(background); } painter->setPen(pen); }
/** * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is * created in the user's home. If no thumbnail can be created, an empty string is returned. */ QString QG_LibraryWidget::getPathToPixmap(const QString& dir, const QString& dxfFile, const QString& dxfPath) { // the thumbnail must be created in the user's home. #if QT_VERSION < 0x040400 QString iconCacheLocation = emu_qt44_storageLocationData() + QDir::separator() + "iconCache" + QDir::separator(); #elif QT_VERSION >= 0x050000 QString iconCacheLocation=QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QDir::separator() + "iconCache" + QDir::separator(); #else QString iconCacheLocation=QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator() + "iconCache" + QDir::separator(); #endif RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: " "dir: '%s' dxfFile: '%s' dxfPath: '%s'", dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data()); // List of all directories that contain part libraries: QStringList directoryList = RS_SYSTEM->getDirectoryList("library"); directoryList.prepend(iconCacheLocation); QStringList::Iterator it; QFileInfo fiDxf(dxfPath); QString itemDir; QString pngPath; // look in all possible system directories for PNG files // in the current library path: for (it=directoryList.begin(); it!=directoryList.end(); ++it) { itemDir = (*it)+dir; pngPath = itemDir + QDir::separator() + fiDxf.baseName() + ".png"; RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: checking: '%s'", pngPath.toLatin1().data()); QFileInfo fiPng(pngPath); // the thumbnail exists: if (fiPng.isFile()) { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s", fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data()); if (fiPng.lastModified() > fiDxf.lastModified()) { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: thumbnail found: '%s'", pngPath.toLatin1().data()); return pngPath; } else { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'", pngPath.toLatin1().data()); } } } // create all directories needed: RS_SYSTEM->createPaths(iconCacheLocation + dir); // QString foo=iconCacheLocation + dir + QDir::separator() + fiDxf.baseName() + ".png"; pngPath = iconCacheLocation + dir + QDir::separator() + fiDxf.baseName() + ".png"; QPixmap* buffer = new QPixmap(128,128); RS_PainterQt painter(buffer); painter.setBackground(RS_Color(255,255,255)); painter.eraseRect(0,0, 128,128); RS_StaticGraphicView gv(128,128, &painter); RS_Graphic graphic; if (graphic.open(dxfPath, RS2::FormatUnknown)) { gv.setContainer(&graphic); gv.zoomAuto(false); // gv.drawEntity(&graphic, true); for (RS_Entity* e=graphic.firstEntity(RS2::ResolveAll); e; e=graphic.nextEntity(RS2::ResolveAll)) { if (e->rtti() != RS2::EntityHatch){ RS_Pen pen = e->getPen(); pen.setColor(Qt::black); e->setPen(pen); } gv.drawEntity(&painter, e); } QImageWriter iio; QImage img; img = buffer->toImage(); img = img.scaled(64,64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); // iio.setImage(img); iio.setFileName(pngPath); iio.setFormat("PNG"); if (!iio.write(img)) { pngPath = ""; RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'", pngPath.toLatin1().data()); } } else { RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data()); } // GraphicView deletes painter painter.end(); delete buffer; return pngPath; }