void RS_ActionDrawEllipseAxis::trigger() { RS_PreviewActionInterface::trigger(); RS_EllipseData ellipseData(center, major, ratio, angle1, angle2, false); RS_Ellipse* ellipse = new RS_Ellipse(container, ellipseData); ellipse->setLayerToActive(); ellipse->setPenToActive(); container->addEntity(ellipse); // upd. undo list: if (document!=NULL) { document->startUndoCycle(); document->addUndoable(ellipse); document->endUndoCycle(); } RS_Vector rz = graphicView->getRelativeZero(); graphicView->redraw(RS2::RedrawDrawing); graphicView->moveRelativeZero(rz); drawSnapper(); setStatus(SetCenter); RS_DEBUG->print("RS_ActionDrawEllipseAxis::trigger():" " entity added: %d", ellipse->getId()); }
void RS_ActionDrawEllipseAxis::trigger() { RS_PreviewActionInterface::trigger(); RS_Ellipse* ellipse = new RS_Ellipse{container, {pPoints->center, pPoints->m_vMajorP, pPoints->ratio, pPoints->angle1, pPoints->angle2, false} }; if (pPoints->ratio > 1.){ ellipse->switchMajorMinor(); } ellipse->setLayerToActive(); ellipse->setPenToActive(); container->addEntity(ellipse); // upd. undo list: if (document) { document->startUndoCycle(); document->addUndoable(ellipse); document->endUndoCycle(); } RS_Vector rz = graphicView->getRelativeZero(); graphicView->redraw(RS2::RedrawDrawing); graphicView->moveRelativeZero(rz); drawSnapper(); setStatus(SetCenter); RS_DEBUG->print("RS_ActionDrawEllipseAxis::trigger():" " entity added: %d", ellipse->getId()); }
void RS_ActionDrawEllipseFociPoint::trigger() { RS_PreviewActionInterface::trigger(); RS_EllipseData ed(center, major*d, sqrt(d*d-c*c)/d, 0., 0.,false); RS_Ellipse* ellipse = new RS_Ellipse(container, ed); ellipse->setLayerToActive(); ellipse->setPenToActive(); container->addEntity(ellipse); // upd. undo list: if (document!=NULL) { document->startUndoCycle(); document->addUndoable(ellipse); document->endUndoCycle(); } // RS_Vector rz = graphicView->getRelativeZero(); graphicView->moveRelativeZero(ellipse->getCenter()); graphicView->redraw(RS2::RedrawDrawing); drawSnapper(); setStatus(SetFocus1); RS_DEBUG->print("RS_ActionDrawEllipseFociPoint::trigger():" " entity added: %d", ellipse->getId()); }
void DL_Jww::CreateEnko(DL_CreationInterface* creationInterface, CDataEnko& DEnko) { string lName = HEX[DEnko.m_nGLayer > ArraySize(HEX)-1 ? ArraySize(HEX)-1: DEnko.m_nGLayer] + "-" + HEX[DEnko.m_nLayer > ArraySize(HEX)-1 ? ArraySize(HEX)-1: DEnko.m_nLayer]; // add layer creationInterface->addLayer(DL_LayerData(lName,0)); int width; if(DEnko.m_nPenWidth > 26) width = 0; else width = DEnko.m_nPenWidth; int color = colTable[DEnko.m_nPenColor > ArraySize(colTable)-1 ? ArraySize(colTable)-1 : DEnko.m_nPenColor]; attrib = DL_Attributes(values[8], // layer color, // color width, // width lTable[DEnko.m_nPenStyle > ArraySize(lTable)-1 ? ArraySize(lTable)-1 : DEnko.m_nPenStyle]); // linetype creationInterface->setAttributes(attrib); creationInterface->setExtrusion(0.0, 0.0, 1.0, 0.0 ); double angle1, angle2; //正円 if(DEnko.m_bZenEnFlg){ if(DEnko.m_dHenpeiRitsu == 1.0){ DL_CircleData d(DEnko.m_start.x, DEnko.m_start.y, 0.0, DEnko.m_dHankei); creationInterface->addCircle(d); }else{ double angle1, angle2; if(DEnko.m_radEnkoKaku > 0.0){ angle1 = DEnko.m_radKaishiKaku; angle2 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku; }else{ angle1 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku; angle2 = DEnko.m_radKaishiKaku; } angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0; angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0; if( angle2 <= angle1 ) angle1 = angle1 - M_PI * 2.0; //楕円 DL_EllipseData d(DEnko.m_start.x, DEnko.m_start.y, 0.0, DEnko.m_dHankei * cos(DEnko.m_radKatamukiKaku), DEnko.m_dHankei * sin(DEnko.m_radKatamukiKaku), 0.0, DEnko.m_dHenpeiRitsu, angle1, angle2); creationInterface->addEllipse(d); } }else{ if(DEnko.m_dHenpeiRitsu == 1.0){ //円弧 if(DEnko.m_radEnkoKaku > 0.0){ angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku; angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku; }else{ angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku; angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku; } angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0; angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0; if( angle2 <= angle1 ) angle1 = angle1 - M_PI * 2.0; DL_ArcData d(DEnko.m_start.x, DEnko.m_start.y, 0.0, DEnko.m_dHankei, Deg(angle1), Deg(angle2)); creationInterface->addArc(d); }else{ double angle1, angle2; if(DEnko.m_radEnkoKaku > 0.0){ angle1 = DEnko.m_radKaishiKaku; angle2 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku; }else{ angle1 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku; angle2 = DEnko.m_radKaishiKaku; } angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0; angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0; if( angle2 <= angle1 ) angle1 = angle1 - M_PI * 2.0; //楕円 DL_EllipseData d(DEnko.m_start.x, DEnko.m_start.y, 0.0, DEnko.m_dHankei * cos(DEnko.m_radKatamukiKaku), DEnko.m_dHankei * sin(DEnko.m_radKatamukiKaku), 0.0, DEnko.m_dHenpeiRitsu, angle1, angle2); creationInterface->addEllipse(d); } } #ifdef FINISHED RS_CircleData data1(RS_Vector(0.0, 0.0), 0.0); RS_Circle* circle; RS_ArcData arc_data(RS_Vector(0.0, 0.0), 0.0, 0.0, 0.0, false); RS_Arc* arc; RS_Ellipse* elps; //正円 if(DEnko.m_bZenEnFlg){ if(DEnko.m_dHenpeiRitsu == 1.0){ data1.center = RS_Vector(DEnko.m_start.x, DEnko.m_start.y); data1.radius = DEnko.m_dHankei; circle = new RS_Circle(graphic, data1); RS2::LineType ltype = lTable[DEnko.m_nPenStyle]; RS_Color col = colTable[DEnko.m_nPenColor]; RS2::LineWidth lw = lWidth[DEnko.m_nPenWidth > 26 ? 0 : DEnko.m_nPenWidth];//RS2::Width12 circle->setPen(RS_Pen(col, lw, ltype)); RS_String lName = HEX[DEnko.m_nGLayer > 0x0f ? 0:DEnko.m_nGLayer] + "-" + HEX[DEnko.m_nLayer > 0x0f ? 0: DEnko.m_nLayer]; if( graphic->findLayer(lName) == (RS_Layer*)NULL ){ #ifdef DEBUG std::cout << lName.ascii() << std::endl; #endif RS_Layer* layer = new RS_Layer(lName); graphic->addLayer(layer); } circle->setLayer(lName); // add the line to the graphic graphic->addEntity(circle); #ifdef DEBUG std::cout << *circle; #endif }else{ //楕円 double angle1, angle2; if(DEnko.m_radEnkoKaku > 0.0){ angle1 = DEnko.m_radKaishiKaku; angle2 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku; }else{ angle1 = DEnko.m_radKaishiKaku + DEnko.m_radEnkoKaku; angle2 = DEnko.m_radKaishiKaku; } angle1 = angle1 - floor(angle1 / (M_PI * 2.0)) * M_PI * 2.0; angle2 = angle2 - floor(angle2 / (M_PI * 2.0)) * M_PI * 2.0; if( angle2 <= angle1 ) angle1 = angle1 - M_PI * 2.0; RS_EllipseData elps_data(RS_Vector(DEnko.m_start.x, DEnko.m_start.y), RS_Vector(DEnko.m_dHankei * cos(DEnko.m_radKatamukiKaku), DEnko.m_dHankei * sin(DEnko.m_radKatamukiKaku)), DEnko.m_dHenpeiRitsu, angle1, angle2, false); elps = new RS_Ellipse(graphic, elps_data); RS2::LineType ltype = lTable[DEnko.m_nPenStyle]; RS_Color col = colTable[DEnko.m_nPenColor]; RS2::LineWidth lw = lWidth[DEnko.m_nPenWidth > 26 ? 0 : DEnko.m_nPenWidth];//RS2::Width12 elps->setPen(RS_Pen(col, lw, ltype)); RS_String lName = HEX[DEnko.m_nGLayer > 0x0f ? 0:DEnko.m_nGLayer] + "-" + HEX[DEnko.m_nLayer > 0x0f ? 0: DEnko.m_nLayer]; if( graphic->findLayer(lName) == (RS_Layer*)NULL ){ RS_Layer* layer = new RS_Layer(lName); graphic->addLayer(layer); } elps->setLayer(lName); // add the line to the graphic graphic->addEntity(elps); } }else{ //円弧 arc_data.center = RS_Vector(DEnko.m_start.x, DEnko.m_start.y); arc_data.radius = DEnko.m_dHankei; if(DEnko.m_radEnkoKaku > 0.0){ arc_data.angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku; arc_data.angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku; }else{ arc_data.angle1 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku + DEnko.m_radEnkoKaku; arc_data.angle2 = DEnko.m_radKaishiKaku + DEnko.m_radKatamukiKaku; } if( arc_data.angle2 <= arc_data.angle1 ) arc_data.angle1 = arc_data.angle1 - M_PI * 2.0; arc_data.angle1 = Deg(arc_data.angle1); arc_data.angle2 = Deg(arc_data.angle2); arc_data.reversed = false; arc = new RS_Arc(graphic, arc_data); RS2::LineType ltype = lTable[DEnko.m_nPenStyle]; RS_Color col = colTable[DEnko.m_nPenColor]; RS2::LineWidth lw = lWidth[DEnko.m_nPenWidth > 26 ? 0 : DEnko.m_nPenWidth];//RS2::Width12 arc->setPen(RS_Pen(col, lw, ltype)); RS_String lName = HEX[DEnko.m_nGLayer > 0x0f ? 0:DEnko.m_nGLayer] + "-" + HEX[DEnko.m_nLayer > 0x0f ? 0: DEnko.m_nLayer]; if( graphic->findLayer(lName) == (RS_Layer*)NULL ){ #ifdef DEBUG std::cout << lName.ascii() << std::endl; #endif RS_Layer* layer = new RS_Layer(lName); graphic->addLayer(layer); } arc->setLayer(lName); // add the line to the graphic graphic->addEntity(arc); } #endif }
/** * 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"); }
/** * Testing function. */ void LC_SimpleTests::slotTestInsertEllipse() { RS_DEBUG->print("%s\n: begin\n", __func__); auto appWin=QC_ApplicationWindow::getAppWindow(); RS_Document* d = appWin->getDocument(); if (d) { RS_Graphic* graphic = (RS_Graphic*)d; if (!graphic) { return; } RS_Ellipse* ellipse; RS_Line* line; for (double a=0.; a<2.*M_PI; a+=0.1) { RS_Vector v = RS_Vector::polar(50., a); double xp = 1000.*a; ellipse = new RS_Ellipse(graphic, {xp,0.}, v, 0.5, 0., 2.*M_PI, false); ellipse->setPen(RS_Pen(RS_Color(255, 0, 255), RS2::Width01, RS2::SolidLine)); graphic->addEntity(ellipse); //graphic->addEntity(new RS_Point(graphic, ellipse->getMax())); //graphic->addEntity(new RS_Point(graphic, ellipse->getMin())); line = new RS_Line{graphic, {xp, 0.}, RS_Vector{xp, 0.}+v}; line->setPen(RS_Pen(RS_Color(128, 128, 128), RS2::Width01, RS2::SolidLine)); graphic->addEntity(line); /* for (double mx=-60.0; mx<60.0; mx+=1.0) { //for (double mx=0.0; mx<1.0; mx+=2.5) { RS_VectorSolutions sol = ellipse->mapX(xp + mx); //graphic->addEntity(new RS_Point(graphic, // sol.vector2 + RS_Vector(a*500.0, 0.0))); //graphic->addEntity(new RS_Point(graphic, // sol.vector3 + RS_Vector(a*500.0, 0.0))); //graphic->addEntity(new RS_Point(graphic, // sol.vector4 + RS_Vector(a*500.0, 0.0))); line = new RS_Line(graphic, RS_LineData(RS_Vector(xp+mx,-50.0), RS_Vector(xp+mx,50.0))); line->setPen(RS_Pen(RS_Color(60, 60, 60), RS2::Width01, RS2::SolidLine)); graphic->addEntity(line); graphic->addEntity(new RS_Point(graphic, sol.get(0))); } */ } // different minor/minor relations /* double x, y; for (y=-250.0; y<=250.0; y+=50.0) { for (x=-250.0; x<=250.0; x+=50.0) { RS_Vector v(x, y); ellipse = new RS_Ellipse(graphic, v, RS_Vector((x/5+50.0)/2.0, 0.0), fabs(x/y), 0.0, 2*M_PI, false); ellipse->setPen(RS_Pen(RS_Color(255, 255, 0), RS2::Width01, RS2::DashDotLine)); graphic->addEntity(ellipse); graphic->addEntity(new RS_Point(graphic, ellipse->getMax())); graphic->addEntity(new RS_Point(graphic, ellipse->getMin())); ellipse = new RS_Ellipse(graphic, v + RS_Vector(750.0, 0.0), RS_Vector((x/5+50.0)/2.0, 0.0), fabs(x/y), 2*M_PI, 0.0, true); graphic->addEntity(ellipse); graphic->addEntity(new RS_Point(graphic, ellipse->getMax())); graphic->addEntity(new RS_Point(graphic, ellipse->getMin())); } } */ /* // different rotation angles: double rot; for (rot=0.0; rot<=2*M_PI+0.1; rot+=(M_PI/8)) { ellipse = new RS_Ellipse(graphic, RS_Vector(rot*200, 500.0), RS_Vector(50.0, 0.0).rotate(rot), 0.3, 0.0, 2*M_PI, false); graphic->addEntity(ellipse); graphic->addEntity(new RS_Point(graphic, ellipse->getMax())); graphic->addEntity(new RS_Point(graphic, ellipse->getMin())); } // different arc angles: double a1, a2; for (rot=0.0; rot<=2*M_PI+0.1; rot+=(M_PI/8)) { for (a1=0.0; a1<=2*M_PI+0.1; a1+=(M_PI/8)) { for (a2=a1+M_PI/8; a2<=2*M_PI+a1+0.1; a2+=(M_PI/8)) { ellipse = new RS_Ellipse(graphic, RS_Vector(-500.0-a1*200.0-5000.0*rot, 500.0-a2*200.0), RS_Vector(50.0, 0.0).rotate(rot), 0.3, a1, a2, false); graphic->addEntity(ellipse); graphic->addEntity(new RS_Point(graphic, ellipse->getMax())); graphic->addEntity(new RS_Point(graphic, ellipse->getMin())); } } } */ RS_GraphicView* v = appWin->getGraphicView(); if (v) { v->redraw(); } } RS_DEBUG->print("%s\n: end\n", __func__); }
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 Plugin_Entity::getData(QHash<int, QVariant> *data){ if (entity == NULL) return; RS2::EntityType et = entity->rtti(); data->insert(DPI::EID, (qulonglong)entity->getId()); data->insert(DPI::LAYER, entity->getLayer()->getName() ); data->insert(DPI::LTYPE, Converter.lt2str(entity->getPen().getLineType()) ); data->insert(DPI::LWIDTH, Converter.lw2str(entity->getPen().getWidth()) ); data->insert(DPI::COLOR, entity->getPen().getColor() ); switch (et) { //atomicEntity case RS2::EntityLine: { data->insert(DPI::ETYPE, DPI::LINE); RS_LineData d = static_cast<RS_Line*>(entity)->getData(); data->insert(DPI::STARTX, d.startpoint.x ); data->insert(DPI::STARTY, d.startpoint.y ); data->insert(DPI::ENDX, d.endpoint.x ); data->insert(DPI::ENDY, d.endpoint.y ); break;} case RS2::EntityPoint: { data->insert(DPI::ETYPE, DPI::POINT); RS_PointData d = static_cast<RS_Point*>(entity)->getData(); data->insert(DPI::STARTX, d.pos.x ); data->insert(DPI::STARTY, d.pos.y ); break; } case RS2::EntityArc: { data->insert(DPI::ETYPE, DPI::ARC); RS_ArcData d = static_cast<RS_Arc*>(entity)->getData(); data->insert(DPI::STARTX, d.center.x ); data->insert(DPI::STARTY, d.center.y ); data->insert(DPI::RADIUS, d.radius ); data->insert(DPI::STARTANGLE, d.angle1 ); data->insert(DPI::ENDANGLE, d.angle2 ); data->insert(DPI::REVERSED, d.reversed ); break;} case RS2::EntityCircle: { data->insert(DPI::ETYPE, DPI::CIRCLE); RS_CircleData d = static_cast<RS_Circle*>(entity)->getData(); data->insert(DPI::STARTX, d.center.x ); data->insert(DPI::STARTY, d.center.y ); data->insert(DPI::RADIUS, d.radius ); break;} case RS2::EntityEllipse: { data->insert(DPI::ETYPE, DPI::ELLIPSE); // RS_EllipseData d = static_cast<RS_Ellipse*>(entity)->getData(); RS_Ellipse *dd = static_cast<RS_Ellipse*>(entity); data->insert(DPI::STARTX, dd->getCenter().x );//10 data->insert(DPI::STARTY, dd->getCenter().y );//20 data->insert(DPI::ENDX, dd->getMajorP().x );//11 endpoint major axis x data->insert(DPI::ENDY, dd->getMajorP().y );//21 endpoint major axis y data->insert(DPI::HEIGHT, dd->getRatio() );//40 major/minor axis ratio data->insert(DPI::STARTANGLE, dd->getAngle1() ); data->insert(DPI::ENDANGLE, dd->getAngle2() ); data->insert(DPI::REVERSED, dd->isReversed() ); break;} case RS2::EntitySolid: //TODO //Only used in dimensions ? data->insert(DPI::ETYPE, DPI::SOLID); break; case RS2::EntityConstructionLine: //Unused ? data->insert(DPI::ETYPE, DPI::CONSTRUCTIONLINE); break; case RS2::EntityImage: { data->insert(DPI::ETYPE, DPI::IMAGE); RS_ImageData d = static_cast<RS_Image*>(entity)->getData(); data->insert(DPI::STARTX, d.insertionPoint.x ); data->insert(DPI::STARTY, d.insertionPoint.y ); break;} case RS2::EntityOverlayBox: //Unused ? data->insert(DPI::ETYPE, DPI::OVERLAYBOX); break; //EntityContainer case RS2::EntityInsert: { data->insert(DPI::ETYPE, DPI::INSERT); RS_InsertData d = static_cast<RS_Insert*>(entity)->getData(); data->insert(DPI::STARTX, d.insertionPoint.x ); data->insert(DPI::STARTY, d.insertionPoint.y ); data->insert(DPI::BLKNAME, d.name ); data->insert(DPI::STARTANGLE, d.angle ); data->insert(DPI::XSCALE, d.scaleFactor.x ); data->insert(DPI::YSCALE, d.scaleFactor.y ); break;} case RS2::EntityText: { data->insert(DPI::ETYPE, DPI::TEXT); RS_TextData d = static_cast<RS_Text*>(entity)->getData(); data->insert(DPI::STARTX, d.insertionPoint.x ); data->insert(DPI::STARTY, d.insertionPoint.y ); data->insert(DPI::STARTANGLE, d.angle ); data->insert(DPI::HEIGHT, d.height ); data->insert(DPI::TEXTCONTENT, d.text ); break;} case RS2::EntityHatch: data->insert(DPI::ETYPE, DPI::HATCH); break; case RS2::EntitySpline: data->insert(DPI::ETYPE, DPI::SPLINE); break; case RS2::EntityPolyline: data->insert(DPI::ETYPE, DPI::POLYLINE); data->insert(DPI::CLOSEPOLY, static_cast<RS_Polyline*>(entity)->isClosed() ); break; case RS2::EntityVertex: data->insert(DPI::ETYPE, DPI::UNKNOWN); break; case RS2::EntityDimAligned: data->insert(DPI::ETYPE, DPI::DIMALIGNED); break; case RS2::EntityDimLinear: data->insert(DPI::ETYPE, DPI::DIMLINEAR); break; case RS2::EntityDimRadial: data->insert(DPI::ETYPE, DPI::DIMRADIAL); break; case RS2::EntityDimDiametric: data->insert(DPI::ETYPE, DPI::DIMDIAMETRIC); break; case RS2::EntityDimAngular: data->insert(DPI::ETYPE, DPI::DIMANGULAR); break; case RS2::EntityDimLeader: data->insert(DPI::ETYPE, DPI::DIMLEADER); break; case RS2::EntityUnknown: default: data->insert(DPI::ETYPE, DPI::UNKNOWN); break; } }
/** construct a ellipse or hyperbola as the path of center of common tangent circles of this two given entities*/ LC_Quadratic::LC_Quadratic(const RS_AtomicEntity* circle0, const RS_AtomicEntity* circle1, bool mirror): m_mQuad(2,2) ,m_vLinear(2) ,m_bValid(false) { // DEBUG_HEADER if(!( circle0->isArcCircleLine() && circle1->isArcCircleLine())) { return; } if(circle1->rtti() != RS2::EntityLine) std::swap(circle0, circle1); if(circle0->rtti() == RS2::EntityLine) { //two lines RS_Line* line0=(RS_Line*) circle0; RS_Line* line1=(RS_Line*) circle1; auto centers=RS_Information::getIntersection(line0,line1); // DEBUG_HEADER if(centers.size()!=1) return; double angle=0.5*(line0->getAngle1()+line1->getAngle1()); m_bValid=true; m_bIsQuadratic=true; m_mQuad(0,0)=0.; m_mQuad(0,1)=0.5; m_mQuad(1,0)=0.5; m_mQuad(1,1)=0.; m_vLinear(0)=0.; m_vLinear(1)=0.; m_dConst=0.; rotate(angle); move(centers.get(0)); // DEBUG_HEADER // std::cout<<*this<<std::endl; return; } if(circle1->rtti() == RS2::EntityLine) { // DEBUG_HEADER //one line, one circle const RS_Line* line1=static_cast<const RS_Line*>(circle1); RS_Vector normal=line1->getNormalVector()*circle0->getRadius(); RS_Vector disp=line1->getNearestPointOnEntity(circle0->getCenter(), false)-circle0->getCenter(); if(normal.dotP(disp)>0.) normal *= -1.; if(mirror) normal *= -1.; RS_Line directrix{line1->getStartpoint()+normal, line1->getEndpoint()+normal}; LC_Quadratic lc0(&directrix,circle0->getCenter()); *this = lc0; return; m_mQuad=lc0.getQuad(); m_vLinear=lc0.getLinear(); m_bIsQuadratic=true; m_bValid=true; m_dConst=lc0.m_dConst; return; } //two circles double const f=(circle0->getCenter()-circle1->getCenter()).magnitude()*0.5; double const a=fabs(circle0->getRadius()+circle1->getRadius())*0.5; double const c=fabs(circle0->getRadius()-circle1->getRadius())*0.5; // DEBUG_HEADER // qDebug()<<"circle center to center distance="<<2.*f<<"\ttotal radius="<<2.*a; if(a<RS_TOLERANCE) return; RS_Vector center=(circle0->getCenter()+circle1->getCenter())*0.5; double angle=center.angleTo(circle0->getCenter()); if( f<a){ //ellipse double const ratio=sqrt(a*a - f*f)/a; RS_Vector const& majorP=RS_Vector{angle}*a; RS_Ellipse const ellipse{center,majorP,ratio,0.,0.,false}; auto const& lc0=ellipse.getQuadratic(); m_mQuad=lc0.getQuad(); m_vLinear=lc0.getLinear(); m_bIsQuadratic=lc0.isQuadratic(); m_bValid=lc0.isValid(); m_dConst=lc0.m_dConst; // DEBUG_HEADER // std::cout<<"ellipse: "<<*this; return; } // DEBUG_HEADER if(c<RS_TOLERANCE){ //two circles are the same radius //degenerate hypberbola: straight lines //equation xy = 0 m_bValid=true; m_bIsQuadratic=true; m_mQuad(0,0)=0.; m_mQuad(0,1)=0.5; m_mQuad(1,0)=0.5; m_mQuad(1,1)=0.; m_vLinear(0)=0.; m_vLinear(1)=0.; m_dConst=0.; rotate(angle); move(center); return; } //hyperbola // equation: x^2/c^2 - y^2/(f^2 -c ^2) = 1 // f: from hyperbola center to one circle center // c: half of difference of two circles double b2= f*f - c*c; m_bValid=true; m_bIsQuadratic=true; m_mQuad(0,0)=1./(c*c); m_mQuad(0,1)=0.; m_mQuad(1,0)=0.; m_mQuad(1,1)=-1./b2; m_vLinear(0)=0.; m_vLinear(1)=0.; m_dConst=-1.; rotate(angle); move(center); return; }
/** * 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"); }
/** * Creates a tangent between a given point and a circle or arc. * Out of the 2 possible tangents, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which tangent we want (typically a * mouse coordinate). * @param point Point. * @param circle Circle, arc or ellipse entity. */ RS_Line* RS_Creation::createTangent1(const RS_Vector& coord, const RS_Vector& point, RS_Entity* circle) { RS_Line* ret = NULL; RS_Vector circleCenter; // check given entities: if (circle==NULL || !point.valid || (circle->rtti()!=RS2::EntityArc && circle->rtti()!=RS2::EntityCircle && circle->rtti()!=RS2::EntityEllipse)) { return NULL; } if (circle->rtti()==RS2::EntityCircle) { circleCenter = ((RS_Circle*)circle)->getCenter(); } else if (circle->rtti()==RS2::EntityArc) { circleCenter = ((RS_Arc*)circle)->getCenter(); } else if (circle->rtti()==RS2::EntityEllipse) { circleCenter = ((RS_Ellipse*)circle)->getCenter(); } // the two tangent points: RS_VectorSolutions sol; // calculate tangent points for arcs / circles: if (circle->rtti()!=RS2::EntityEllipse) { // create temp. thales circle: RS_Vector tCenter = (point + circleCenter)/2.0; double tRadius = point.distanceTo(tCenter); RS_Circle tmp(NULL, RS_CircleData(tCenter, tRadius)); // get the two intersection points which are the tangent points: sol = RS_Information::getIntersection(&tmp, circle, false); } // calculate tangent points for ellipses: else { RS_Ellipse* el = (RS_Ellipse*)circle; //sol.alloc(2); //sol.set(0, circleCenter); //sol.set(1, circleCenter); double a = el->getMajorRadius(); // the length of the major axis / 2 double b = el->getMinorRadius(); // the length of the minor axis / 2 // rotate and move point: RS_Vector point2 = point; point2.move(-el->getCenter()); point2.rotate(-el->getAngle()); double xp = point2.x; // coordinates of the given point double yp = point2.y; double xt1; // Tangent point 1 double yt1; double xt2; // Tangent point 2 double yt2; double a2 = a * a; double b2 = b * b; double d = a2 / b2 * yp / xp; double e = a2 / xp; double af = b2 * d * d + a2; double bf = -b2 * d * e * 2.0; double cf = b2 * e * e - a2 * b2; double t = sqrt(bf * bf - af * cf * 4.0); yt1 = (t - bf) / (af * 2.0); xt1 = e - d * yt1; yt2 = (-t - bf) / (af * 2.0); xt2 = e - d * yt2; RS_Vector s1 = RS_Vector(xt1, yt1); RS_Vector s2 = RS_Vector(xt2, yt2); s1.rotate(el->getAngle()); s1.move(el->getCenter()); s2.rotate(el->getAngle()); s2.move(el->getCenter()); sol.push_back(s1); sol.push_back(s2); } if (sol.getNumber() < 2 ) { return NULL; } if (!sol.get(0).valid || !sol.get(1).valid) { return NULL; } // create all possible tangents: RS_Line* poss[2]; RS_LineData d; d = RS_LineData(sol.get(0), point); poss[0] = new RS_Line(NULL, d); d = RS_LineData(sol.get(1), point); poss[1] = new RS_Line(NULL, d); // find closest tangent: double minDist = RS_MAXDOUBLE; double dist; int idx = -1; for (int i=0; i<2; ++i) { dist = poss[i]->getDistanceToPoint(coord); if (dist<minDist) { minDist = dist; idx = i; } } // create the closest tangent: if (idx!=-1) { RS_LineData d = poss[idx]->getData(); for (int i=0; i<2; ++i) { delete poss[i]; } if (document!=NULL && handleUndo) { document->startUndoCycle(); } ret = new RS_Line(container, d); ret->setLayerToActive(); ret->setPenToActive(); if (container!=NULL) { container->addEntity(ret); } if (document!=NULL && handleUndo) { document->addUndoable(ret); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(ret); } } else { ret = NULL; } return ret; }