void RS_ActionDrawArc3P::trigger() { RS_PreviewActionInterface::trigger(); preparePreview(); if (data.isValid()) { RS_Arc* arc = new RS_Arc(container, data); arc->setLayerToActive(); arc->setPenToActive(); container->addEntity(arc); // upd. undo list: if (document!=NULL) { document->startUndoCycle(); document->addUndoable(arc); document->endUndoCycle(); } deleteSnapper(); graphicView->moveRelativeZero(RS_Vector(0.0,0.0)); graphicView->drawEntity(arc); graphicView->moveRelativeZero(arc->getEndpoint()); drawSnapper(); setStatus(SetPoint1); reset(); } else { //RS_DIALOGFACTORY->requestWarningDialog(tr("Invalid arc data.")); RS_DIALOGFACTORY->commandMessage(tr("Invalid arc data.")); } }
void RS_ActionDrawArcTangential::trigger() { RS_PreviewActionInterface::trigger(); if (point.valid==false || baseEntity==NULL) { RS_DEBUG->print("RS_ActionDrawArcTangential::trigger: " "conditions not met"); return; } preparePreview(); RS_Arc* arc = new RS_Arc(container, *data); arc->setLayerToActive(); arc->setPenToActive(); container->addEntity(arc); // upd. undo list: if (document!=NULL) { document->startUndoCycle(); document->addUndoable(arc); document->endUndoCycle(); } graphicView->redraw(RS2::RedrawDrawing); graphicView->moveRelativeZero(arc->getCenter()); setStatus(SetBaseEntity); reset(); }
/** * Helper function for makeContour * Modify newEntity to parellel of orgEntity at distance dist * If dist is positive the offset is in left else in right * Bot newEntity and orgEntity are the same type of entity * if not return NULL pointer * * @retval RS_Entity* of parellel entity * * @author Rallaz */ RS_Entity* RS_ActionPolylineEquidistant::calculateOffset(RS_Entity* newEntity,RS_Entity* orgEntity, double dist) { if (orgEntity->rtti()==RS2::EntityArc && newEntity->rtti()==RS2::EntityArc) { RS_Arc* arc = (RS_Arc*)newEntity; double r0 = ((RS_Arc*)orgEntity)->getRadius(); double r; if ( ((RS_Arc*)orgEntity)->isReversed()) r = r0 + dist; else r = r0 - dist; if(r < 0) return NULL; arc->setData(((RS_Arc*)orgEntity)->getData()); arc->setRadius(r); arc->calculateEndpoints(); return newEntity; } else if (orgEntity->rtti()==RS2::EntityLine && newEntity->rtti()==RS2::EntityLine) { RS_Line* line0 = (RS_Line*)orgEntity; RS_Line* line1 = (RS_Line*)newEntity; RS_Vector v0 = line0->getStartpoint(); RS_Vector v1(v0.x,v0.y+dist); RS_Vector v2(v0.x+line0->getLength(),v0.y+dist); line1->setStartpoint(v1); line1->setEndpoint(v2); line1->rotate(v0, line0->getAngle1()); return newEntity; } return NULL; }
void RS_ActionDrawArc::trigger() { RS_PreviewActionInterface::trigger(); RS_Arc* arc = new RS_Arc(container, data); arc->setLayerToActive(); arc->setPenToActive(); container->addEntity(arc); // upd. undo list: if (document!=NULL) { document->startUndoCycle(); document->addUndoable(arc); document->endUndoCycle(); } graphicView->redraw(RS2::RedrawDrawing); graphicView->moveRelativeZero(arc->getCenter()); setStatus(SetCenter); reset(); RS_DEBUG->print("RS_ActionDrawArc::trigger(): arc added: %d", arc->getId()); }
void RS_ActionDimDiametric::preparePreview() { if (entity) { double radius{0.}; RS_Vector center{false}; if (entity->rtti()==RS2::EntityArc) { RS_Arc* p = static_cast<RS_Arc*>(entity); radius = p->getRadius(); center = p->getCenter(); } else if (entity->rtti()==RS2::EntityCircle) { RS_Circle* p = static_cast<RS_Circle*>(entity); radius = p->getRadius(); center = p->getCenter(); } double angle = center.angleTo(*pos); data->definitionPoint.setPolar(radius, angle + M_PI); data->definitionPoint += center; edata->definitionPoint.setPolar(radius, angle); edata->definitionPoint += center; } }
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 }
/** * Checks if the given coordinate is inside the given contour. * * @param point Coordinate to check. * @param contour One or more entities which shape a contour. * If the given contour is not closed, the result is undefined. * The entities don't need to be in a specific order. * @param onContour Will be set to true if the given point it exactly * on the contour. */ bool RS_Information::isPointInsideContour(const RS_Vector& point, RS_EntityContainer* contour, bool* onContour) { if (contour==NULL) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Information::isPointInsideContour: contour is NULL"); return false; } if (point.x < contour->getMin().x || point.x > contour->getMax().x || point.y < contour->getMin().y || point.y > contour->getMax().y) { return false; } double width = contour->getSize().x+1.0; bool sure; int counter; int tries = 0; double rayAngle = 0.0; do { sure = true; // create ray: RS_Vector v; v.setPolar(width*10.0, rayAngle); RS_Line ray(NULL, RS_LineData(point, point+v)); counter = 0; RS_VectorSolutions sol; if (onContour!=NULL) { *onContour = false; } for (RS_Entity* e = contour->firstEntity(RS2::ResolveAll); e!=NULL; e = contour->nextEntity(RS2::ResolveAll)) { // intersection(s) from ray with contour entity: sol = RS_Information::getIntersection(&ray, e, true); for (int i=0; i<=1; ++i) { RS_Vector p = sol.get(i); if (p.valid) { // point is on the contour itself if (p.distanceTo(point)<1.0e-5) { if (onContour!=NULL) { *onContour = true; } } else { if (e->rtti()==RS2::EntityLine) { RS_Line* line = (RS_Line*)e; // ray goes through startpoint of line: if (p.distanceTo(line->getStartpoint())<1.0e-4) { if (RS_Math::correctAngle(line->getAngle1())<M_PI) { counter++; sure = false; } } // ray goes through endpoint of line: else if (p.distanceTo(line->getEndpoint())<1.0e-4) { if (RS_Math::correctAngle(line->getAngle2())<M_PI) { counter++; sure = false; } } // ray goes through the line: else { counter++; } } else if (e->rtti()==RS2::EntityArc) { RS_Arc* arc = (RS_Arc*)e; if (p.distanceTo(arc->getStartpoint())<1.0e-4) { double dir = arc->getDirection1(); if ((dir<M_PI && dir>=1.0e-5) || ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) && arc->getCenter().y>p.y)) { counter++; sure = false; } } else if (p.distanceTo(arc->getEndpoint())<1.0e-4) { double dir = arc->getDirection2(); if ((dir<M_PI && dir>=1.0e-5) || ((dir>2*M_PI-1.0e-5 || dir<1.0e-5) && arc->getCenter().y>p.y)) { counter++; sure = false; } } else { counter++; } } else if (e->rtti()==RS2::EntityCircle) { // tangent: if (i==0 && sol.get(1).valid==false) { if (!sol.isTangent()) { counter++; } else { sure = false; } } else if (i==1 || sol.get(1).valid==true) { counter++; } } } } } } rayAngle+=0.02; tries++; } while (!sure && rayAngle<2*M_PI && tries<6); // remove double intersections: /* QList<RS_Vector> is2; bool done; RS_Vector* av; do { done = true; double minDist = RS_MAXDOUBLE; double dist; av = NULL; for (RS_Vector* v = is.first(); v!=NULL; v = is.next()) { dist = point.distanceTo(*v); if (dist<minDist) { minDist = dist; done = false; av = v; } } if (!done && av!=NULL) { is2.append(*av); } } while (!done); */ return ((counter%2)==1); }
/** * 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"); }
/** * Updates the sub entities of this dimension. Called when the * dimension or the position, alignment, .. changes. * * @param autoText Automatically reposition the text label */ void RS_DimAngular::update(bool /*autoText*/) { RS_DEBUG->print("RS_DimAngular::update"); clear(); if (isUndone()) { return; } // distance from entities (DIMEXO) double dimexo = getExtensionLineOffset(); // extension line extension (DIMEXE) double dimexe = getExtensionLineExtension(); // text height (DIMTXT) double dimtxt = getTextHeight(); // text distance to line (DIMGAP) double dimgap = getDimensionLineGap(); // find out center: RS_Vector center = getCenter(); if (!center.valid) { return; } double ang1 = 0.0; double ang2 = 0.0; bool reversed = false; RS_Vector p1; RS_Vector p2; getAngles(ang1, ang2, reversed, p1, p2); double rad = edata.definitionPoint4.distanceTo(center); RS_Line* line; RS_Vector dir; double len; double dist; // 1st extension line: dist = center.distanceTo(p1); len = rad - dist + dimexe; dir.setPolar(1.0, ang1); line = new RS_Line(this, RS_LineData(center + dir*dist + dir*dimexo, center + dir*dist + dir*len)); line->setPen(RS_Pen(RS2::FlagInvalid)); line->setLayer(NULL); addEntity(line); // 2nd extension line: dist = center.distanceTo(p2); len = rad - dist + dimexe; dir.setPolar(1.0, ang2); line = new RS_Line(this, RS_LineData(center + dir*dist + dir*dimexo, center + dir*dist + dir*len)); line->setPen(RS_Pen(RS2::FlagInvalid)); line->setLayer(NULL); addEntity(line); // Create dimension line (arc): RS_Arc* arc = new RS_Arc(this, RS_ArcData(center, rad, ang1, ang2, reversed)); arc->setPen(RS_Pen(RS2::FlagInvalid)); arc->setLayer(NULL); addEntity(arc); // length of dimension arc: double distance = arc->getLength(); // do we have to put the arrows outside of the arc? bool outsideArrows = (distance<getArrowSize()*2); // arrow angles: double arrowAngle1, arrowAngle2; double arrowAng; if (rad>1.0e-6) { arrowAng = getArrowSize() / rad; } else { arrowAng = 0.0; } RS_Vector v1, v2; if (!arc->isReversed()) { v1.setPolar(rad, arc->getAngle1()+arrowAng); } else { v1.setPolar(rad, arc->getAngle1()-arrowAng); } v1+=arc->getCenter(); arrowAngle1 = arc->getStartpoint().angleTo(v1); if (!arc->isReversed()) { v2.setPolar(rad, arc->getAngle2()-arrowAng); } else { v2.setPolar(rad, arc->getAngle2()+arrowAng); } v2+=arc->getCenter(); arrowAngle2 = arc->getEndpoint().angleTo(v2); if (!outsideArrows) { arrowAngle1 = arrowAngle1+M_PI; arrowAngle2 = arrowAngle2+M_PI; } // Arrows: RS_SolidData sd; RS_Solid* arrow; // arrow 1 arrow = new RS_Solid(this, sd); arrow->shapeArrow(arc->getStartpoint(), arrowAngle1, getArrowSize()); arrow->setPen(RS_Pen(RS2::FlagInvalid)); arrow->setLayer(NULL); addEntity(arrow); // arrow 2: arrow = new RS_Solid(this, sd); arrow->shapeArrow(arc->getEndpoint(), arrowAngle2, getArrowSize()); arrow->setPen(RS_Pen(RS2::FlagInvalid)); arrow->setLayer(NULL); addEntity(arrow); // text label: RS_TextData textData; RS_Vector textPos = arc->getMiddlePoint(); RS_Vector distV; double textAngle; double dimAngle1 = textPos.angleTo(arc->getCenter())-M_PI/2.0; // rotate text so it's readable from the bottom or right (ISO) // quadrant 1 & 4 if (dimAngle1>M_PI/2.0*3.0+0.001 || dimAngle1<M_PI/2.0+0.001) { distV.setPolar(dimgap, dimAngle1+M_PI/2.0); textAngle = dimAngle1; } // quadrant 2 & 3 else { distV.setPolar(dimgap, dimAngle1-M_PI/2.0); textAngle = dimAngle1+M_PI; } // move text away from dimension line: textPos+=distV; textData = RS_TextData(textPos, dimtxt, 30.0, RS2::VAlignBottom, RS2::HAlignCenter, RS2::LeftToRight, RS2::Exact, 1.0, getLabel(), "standard", textAngle); RS_Text* text = new RS_Text(this, textData); // move text to the side: text->setPen(RS_Pen(RS2::FlagInvalid)); text->setLayer(NULL); addEntity(text); calculateBorders(); }
void RS_Font::readCXF(QString path) { QString line; QFile f(path); f.open(QIODevice::ReadOnly); QTextStream ts(&f); // Read line by line until we find a new letter: while (!ts.atEnd()) { line = ts.readLine(); if (line.isEmpty()) continue; // Read font settings: if (line.at(0)=='#') { QStringList lst = ( line.right(line.length()-1) ).split(':', QString::SkipEmptyParts); QStringList::Iterator it3 = lst.begin(); // RVT_PORT sometimes it happens that the size is < 2 if (lst.size()<2) continue; QString identifier = (*it3).trimmed(); it3++; QString value = (*it3).trimmed(); if (identifier.toLower()=="letterspacing") { letterSpacing = value.toDouble(); } else if (identifier.toLower()=="wordspacing") { wordSpacing = value.toDouble(); } else if (identifier.toLower()=="linespacingfactor") { lineSpacingFactor = value.toDouble(); } else if (identifier.toLower()=="author") { authors.append(value); } else if (identifier.toLower()=="name") { names.append(value); } else if (identifier.toLower()=="encoding") { ts.setCodec(QTextCodec::codecForName(value.toLatin1())); encoding = value; } } // Add another letter to this font: else if (line.at(0)=='[') { // uniode character: QChar ch; // read unicode: QRegExp regexp("[0-9A-Fa-f]{4,4}"); regexp.indexIn(line); QString cap = regexp.cap(); if (!cap.isNull()) { int uCode = cap.toInt(nullptr, 16); ch = QChar(uCode); } // read UTF8 (LibreCAD 1 compatibility) else if (line.indexOf(']')>=3) { int i = line.indexOf(']'); QString mid = line.mid(1, i-1); ch = QString::fromUtf8(mid.toLatin1()).at(0); } // read normal ascii character: else { ch = line.at(1); } // create new letter: RS_FontChar* letter = new RS_FontChar(nullptr, ch, RS_Vector(0.0, 0.0)); // Read entities of this letter: QString coordsStr; QStringList coords; QStringList::Iterator it2; do { line = ts.readLine(); if (line.isEmpty()) { continue; } coordsStr = line.right(line.length()-2); // coords = QStringList::split(',', coordsStr); coords = coordsStr.split(',', QString::SkipEmptyParts); it2 = coords.begin(); // Line: if (line.at(0)=='L') { double x1 = (*it2++).toDouble(); double y1 = (*it2++).toDouble(); double x2 = (*it2++).toDouble(); double y2 = (*it2).toDouble(); RS_Line* line = new RS_Line{letter, {{x1, y1}, {x2, y2}}}; line->setPen(RS_Pen(RS2::FlagInvalid)); line->setLayer(nullptr); letter->addEntity(line); } // Arc: else if (line.at(0)=='A') { double cx = (*it2++).toDouble(); double cy = (*it2++).toDouble(); double r = (*it2++).toDouble(); double a1 = RS_Math::deg2rad((*it2++).toDouble()); double a2 = RS_Math::deg2rad((*it2).toDouble()); bool reversed = (line.at(1)=='R'); RS_ArcData ad(RS_Vector(cx,cy), r, a1, a2, reversed); RS_Arc* arc = new RS_Arc(letter, ad); arc->setPen(RS_Pen(RS2::FlagInvalid)); arc->setLayer(nullptr); letter->addEntity(arc); } } while (!line.isEmpty()); if (letter->isEmpty()) { delete letter; } else { letter->calculateBorders(); letterList.add(letter); } } } f.close(); }
/** * Implementation of the method used for RS_Export to communicate * with this filter. * * @param file Full path to the LFF file that will be written. */ bool RS_FilterLFF::fileExport(RS_Graphic& g, const QString& file, RS2::FormatType /*type*/) { RS_DEBUG->print("LFF Filter: exporting file '%s'...", file.toLatin1().data()); RS_DEBUG->print("RS_FilterLFF::fileExport: open"); QFile f(file); QTextStream ts(&f); ts.setCodec("UTF-8"); if (f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { RS_DEBUG->print("RS_FilterLFF::fileExport: open: OK"); RS_DEBUG->print("RS_FilterLFF::fileExport: header"); // header: ts << "# Format: LibreCAD Font 1\n"; ts << QString("# Creator: %1\n").arg(RS_SYSTEM->getAppName()); ts << QString("# Version: %1\n").arg(RS_SYSTEM->getAppVersion()); QString ns = g.getVariableString("Names", ""); if (!ns.isEmpty()) { QStringList names = ns.split(','); RS_DEBUG->print("002"); for (int i = 0; i < names.size(); ++i) { ts << QString("# Name: %1\n").arg(names.at(i)); } } QString es = g.getVariableString("Encoding", ""); ts << QString("# Encoding: UTF-8\n"); ts << QString("# LetterSpacing: %1\n").arg( g.getVariableDouble("LetterSpacing", 3.0)); ts << QString("# WordSpacing: %1\n").arg( g.getVariableDouble("WordSpacing", 6.75)); ts << QString("# LineSpacingFactor: %1\n").arg( g.getVariableDouble("LineSpacingFactor", 1.0)); QString dateline = QDate::currentDate().toString ("yyyy-MM-dd"); ts << QString("# Created: %1\n").arg( g.getVariableString("Created", dateline)); ts << QString("# Last modified: %1\n").arg(dateline); QString sa = g.getVariableString("Authors", ""); RS_DEBUG->print("authors: %s", sa.toLocal8Bit().data()); if (!sa.isEmpty()) { QStringList authors = sa.split(','); RS_DEBUG->print("count: %d", authors.count()); QString a; for (int i = 0; i < authors.size(); ++i) { ts << QString("# Author: %1\n").arg(authors.at(i)); } } es = g.getVariableString("License", ""); if (!es.isEmpty()) { ts << QString("# License: %1\n").arg(es); } else ts << "# License: unknown\n"; RS_DEBUG->print("RS_FilterLFF::fileExport: header: OK"); // iterate through blocks (=letters of font) for (uint i=0; i<g.countBlocks(); ++i) { RS_Block* blk = g.blockAt(i); RS_DEBUG->print("block: %d", i); if (blk!=NULL) { RS_DEBUG->print("002a: %s", (blk->getName().toLocal8Bit().data())); ts << QString("\n%1\n").arg(blk->getName()); // iterate through entities of this letter: for (RS_Entity* e=blk->firstEntity(RS2::ResolveNone); e!=NULL; e=blk->nextEntity(RS2::ResolveNone)) { if (!e->isUndone()) { // lines: if (e->rtti()==RS2::EntityLine) { RS_Line* l = (RS_Line*)e; ts << clearZeros(l->getStartpoint().x, 5) << ','; ts << clearZeros(l->getStartpoint().y, 5) << ';'; ts << clearZeros(l->getEndpoint().x, 5) << ','; ts << clearZeros(l->getEndpoint().y, 5) << '\n'; } // arcs: else if (e->rtti()==RS2::EntityArc) { RS_Arc* a = (RS_Arc*)e; ts << clearZeros(a->getStartpoint().x, 5) << ','; ts << clearZeros(a->getStartpoint().y, 5) << ';'; ts << clearZeros(a->getEndpoint().x, 5) << ','; ts << clearZeros(a->getEndpoint().y, 5) << ",A"; ts << clearZeros(a->getBulge(), 5) << '\n'; } else if (e->rtti()==RS2::EntityBlock) { RS_Block* b = (RS_Block*)e; QString uCode; uCode.setNum(b->getName().at(0).unicode(), 16); if (uCode.length()<4) { uCode = uCode.rightJustified(4, '0'); } ts << QString("C%1\n").arg(uCode); } else if (e->rtti()==RS2::EntityPolyline) { RS_Polyline* p = (RS_Polyline*)e; ts << clearZeros(p->getStartpoint().x, 5) << ','; ts << clearZeros(p->getStartpoint().y, 5); for (RS_Entity* e2=p->firstEntity(RS2::ResolveNone); e2!=NULL; e2=p->nextEntity(RS2::ResolveNone)) { if (e2->rtti()==RS2::EntityLine){ RS_Line* l = (RS_Line*)e2; ts << ';' << clearZeros(l->getEndpoint().x, 5) << ','; ts << clearZeros(l->getEndpoint().y, 5); } else if (e2->rtti()==RS2::EntityArc){ RS_Arc* a = (RS_Arc*)e2; ts << ';' << clearZeros(a->getEndpoint().x, 5) << ','; ts << clearZeros(a->getEndpoint().y, 5) <<",A"; ts << clearZeros(a->getBulge(), 5); } } ts<<'\n'; } // Ignore entities other than arcs / lines else {} } } } } f.close(); RS_DEBUG->print("LFF Filter: exporting file: OK"); return true; } else { RS_DEBUG->print("LFF Filter: exporting file failed"); } return false; }
/** * Testing function. */ void LC_SimpleTests::slotTestDumpEntities(RS_EntityContainer* d){ int level = 0; std::ofstream dumpFile; if (d) { dumpFile.open("debug_entities.html", std::ios::app); ++level; } else { d = QC_ApplicationWindow::getAppWindow()->getDocument(); dumpFile.open("debug_entities.html"); level = 0; } if (d) { if (level==0) { dumpFile << "<html>\n"; dumpFile << "<body>\n"; } for(auto e: *d){ dumpFile << "<table border=\"1\">\n"; dumpFile << "<tr><td>Entity: " << e->getId() << "</td></tr>\n"; dumpFile << "<tr><td><table><tr>" << "<td>VIS:" << e->isVisible() << "</td>" << "<td>UND:" << e->isUndone() << "</td>" << "<td>SEL:" << e->isSelected() << "</td>" << "<td>TMP:" << e->getFlag(RS2::FlagTemp) << "</td>"; QString lay = "NULL"; if (e->getLayer()) { lay = e->getLayer()->getName(); } dumpFile << "<td>Layer: " << lay.toLatin1().data() << "</td>" << "<td>Width: " << (int)e->getPen(false).getWidth() << "</td>" << "<td>Parent: " << e->getParent()->getId() << "</td>" << "</tr></table>"; dumpFile << "<tr><td>\n"; switch (e->rtti()) { case RS2::EntityPoint: { RS_Point* p = (RS_Point*)e; dumpFile << "<table><tr><td>" << "<b>Point:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>" << p->getPos() << "</td>" << "</tr></table>"; } break; case RS2::EntityLine: { RS_Line* l = (RS_Line*)e; dumpFile << "<table><tr><td>" << "<b>Line:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>" << l->getStartpoint() << "</td>" << "<td>" << l->getEndpoint() << "</td>" << "</tr></table>"; } break; case RS2::EntityArc: { RS_Arc* a = (RS_Arc*)e; dumpFile << "<table><tr><td>" << "<b>Arc:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>Center: " << a->getCenter() << "</td>" << "<td>Radius: " << a->getRadius() << "</td>" << "<td>Angle 1: " << a->getAngle1() << "</td>" << "<td>Angle 2: " << a->getAngle2() << "</td>" << "<td>Startpoint: " << a->getStartpoint() << "</td>" << "<td>Endpoint: " << a->getEndpoint() << "</td>" << "<td>reversed: " << (int)a->isReversed() << "</td>" << "</tr></table>"; } break; case RS2::EntityCircle: { RS_Circle* c = (RS_Circle*)e; dumpFile << "<table><tr><td>" << "<b>Circle:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>Center: " << c->getCenter() << "</td>" << "<td>Radius: " << c->getRadius() << "</td>" << "</tr></table>"; } break; case RS2::EntityDimAligned: { RS_DimAligned* d = (RS_DimAligned*)e; dumpFile << "<table><tr><td>" << "<b>Dimension / Aligned:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>" << d->getDefinitionPoint() << "</td>" << "<td>" << d->getExtensionPoint1() << "</td>" << "<td>" << d->getExtensionPoint2() << "</td>" << "<td>Text: " << d->getText().toLatin1().data() << "</td>" << "<td>Label: " << d->getLabel().toLatin1().data() << "</td>" << "</tr></table>"; } break; case RS2::EntityDimLinear: { RS_DimLinear* d = (RS_DimLinear*)e; dumpFile << "<table><tr><td>" << "<b>Dimension / Linear:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>" << d->getDefinitionPoint() << "</td>" << "<td>" << d->getExtensionPoint1() << "</td>" << "<td>" << d->getExtensionPoint2() << "</td>" << "<td>Text: " << d->getText().toLatin1().data() << "</td>" << "<td>Label: " << d->getLabel().toLatin1().data() << "</td>" << "</tr></table>"; } break; case RS2::EntityInsert: { RS_Insert* i = (RS_Insert*)e; dumpFile << "<table><tr><td>" << "<b>Insert:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>Insertion point:" << i->getInsertionPoint() << "</td>" << "</tr></table>"; } break; case RS2::EntityMText: { RS_MText* t = (RS_MText*)e; dumpFile << "<table><tr><td>" << "<b>Text:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>Text:" << t->getText().toLatin1().data() << "</td>" << "<td>Height:" << t->getHeight() << "</td>" << "</tr></table>"; } break; case RS2::EntityText: { RS_Text* t = (RS_Text*)e; dumpFile << "<table><tr><td>" << "<b>Text:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>Text:" << t->getText().toLatin1().data() << "</td>" << "<td>Height:" << t->getHeight() << "</td>" << "</tr></table>"; } break; case RS2::EntityHatch: { RS_Hatch* h = (RS_Hatch*)e; dumpFile << "<table><tr><td>" << "<b>Hatch:</b>" << "</td></tr>"; dumpFile << "<tr>" << "<td>Pattern:" << h->getPattern().toLatin1().data() << "</td>" << "<td>Scale:" << h->getScale() << "</td>" << "<td>Solid:" << (int)h->isSolid() << "</td>" << "</tr></table>"; } break; default: dumpFile << "<tr><td>" << "<b>Unknown Entity: " << e->rtti() << "</b>" << "</td></tr>"; break; } if (e->isContainer() || e->rtti()==RS2::EntityHatch) { RS_EntityContainer* ec = (RS_EntityContainer*)e; dumpFile << "<table><tr><td valign=\"top\"> Contents:</td><td>\n"; dumpFile.close(); slotTestDumpEntities(ec); dumpFile.open("debug_entities.html", std::ios::app); dumpFile << "</td></tr></table>\n"; } dumpFile << "</td></tr>" << "</table>\n" << "<br><br>"; } if (level==0) { dumpFile << "</body>\n"; dumpFile << "</html>\n"; } else { level--; } } 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(); }
/** * 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 arc parallel to the given arc e. * Out of the 2 possible parallels, the one closest to * the given coordinate is returned. * * @param coord Coordinate to define which parallel we want (typically a * mouse coordinate). * @param distance Distance of the parallel. * @param number Number of parallels. * @param e Original entity. * * @return Pointer to the first created parallel or NULL if no * parallel has been created. */ RS_Arc* RS_Creation::createParallelArc(const RS_Vector& coord, double distance, int number, RS_Arc* e) { if (e==NULL) { return NULL; } RS_ArcData parallelData; RS_Arc* ret = NULL; bool inside = (e->getCenter().distanceTo(coord) < e->getRadius()); if (inside) { distance *= -1; } for (int num=1; num<=number; ++num) { // calculate parallel: bool ok = true; RS_Arc parallel1(NULL, e->getData()); parallel1.setRadius(e->getRadius() + distance*num); if (parallel1.getRadius()<0.0) { parallel1.setRadius(RS_MAXDOUBLE); ok = false; } // calculate 2nd parallel: //RS_Arc parallel2(NULL, e->getData()); //parallel2.setRadius(e->getRadius()+distance*num); //double dist1 = parallel1.getDistanceToPoint(coord); //double dist2 = parallel2.getDistanceToPoint(coord); //double minDist = min(dist1, dist2); //if (minDist<RS_MAXDOUBLE) { if (ok==true) { //if (dist1<dist2) { parallelData = parallel1.getData(); //} else { // parallelData = parallel2.getData(); //} if (document!=NULL && handleUndo) { document->startUndoCycle(); } RS_Arc* newArc = new RS_Arc(container, parallelData); newArc->setLayerToActive(); newArc->setPenToActive(); if (ret==NULL) { ret = newArc; } if (container!=NULL) { container->addEntity(newArc); } if (document!=NULL && handleUndo) { document->addUndoable(newArc); document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->drawEntity(newArc); } } } return ret; }
/** * Testing function. */ void LC_SimpleTests::slotTestInsertBlock() { RS_DEBUG->print("%s\n: begin\n", __func__); auto appWin=QC_ApplicationWindow::getAppWindow(); RS_Document* d = appWin->getDocument(); if (d && d->rtti()==RS2::EntityGraphic) { RS_Graphic* graphic = (RS_Graphic*)d; if (graphic==NULL) { return; } graphic->addLayer(new RS_Layer("default")); RS_Block* block = new RS_Block(graphic, RS_BlockData("debugblock", RS_Vector(0.0,0.0), true)); RS_Line* line; RS_Arc* arc; RS_Circle* circle; // Add one red line: line = new RS_Line{block, {0.,0.}, {50.,0.}}; line->setLayerToActive(); line->setPen(RS_Pen(RS_Color(255, 0, 0), RS2::Width01, RS2::SolidLine)); block->addEntity(line); // Add one line with attributes from block: line = new RS_Line{block, {50.,0.}, {50.,50.}}; line->setPen(RS_Pen(RS_Color(RS2::FlagByBlock), RS2::WidthByBlock, RS2::LineByBlock)); block->addEntity(line); // Add one arc with attributes from block: RS_ArcData d({50.,0.}, 50.0, M_PI_2, M_PI, false); arc = new RS_Arc(block, d); arc->setPen(RS_Pen(RS_Color(RS2::FlagByBlock), RS2::WidthByBlock, RS2::LineByBlock)); block->addEntity(arc); // Add one blue circle: RS_CircleData circleData(RS_Vector(20.0,15.0), 12.5); circle = new RS_Circle(block, circleData); circle->setLayerToActive(); circle->setPen(RS_Pen(RS_Color(0, 0, 255), RS2::Width01, RS2::SolidLine)); block->addEntity(circle); graphic->addBlock(block); RS_Insert* ins; RS_InsertData insData("debugblock", RS_Vector(0.0,0.0), RS_Vector(1.0,1.0), 0.0, 1, 1, RS_Vector(0.0, 0.0), NULL, RS2::NoUpdate); // insert one magenta instance of the block (original): ins = new RS_Insert(graphic, insData); ins->setLayerToActive(); ins->setPen(RS_Pen(RS_Color(255, 0, 255), RS2::Width02, RS2::SolidLine)); ins->update(); graphic->addEntity(ins); // insert one green instance of the block (rotate): insData = RS_InsertData("debugblock", RS_Vector(-50.0,20.0), RS_Vector(1.0,1.0), M_PI/6., 1, 1, RS_Vector(0.0, 0.0), NULL, RS2::NoUpdate); ins = new RS_Insert(graphic, insData); ins->setLayerToActive(); ins->setPen(RS_Pen(RS_Color(0, 255, 0), RS2::Width02, RS2::SolidLine)); ins->update(); graphic->addEntity(ins); // insert one cyan instance of the block (move): insData = RS_InsertData("debugblock", RS_Vector(10.0,20.0), RS_Vector(1.0,1.0), 0.0, 1, 1, RS_Vector(0.0, 0.0), NULL, RS2::NoUpdate); ins = new RS_Insert(graphic, insData); ins->setLayerToActive(); ins->setPen(RS_Pen(RS_Color(0, 255, 255), RS2::Width02, RS2::SolidLine)); ins->update(); graphic->addEntity(ins); // insert one blue instance of the block: for (double a=0.0; a<360.0; a+=45.0) { insData = RS_InsertData("debugblock", RS_Vector(60.0,0.0), RS_Vector(2.0/5,2.0/5), RS_Math::deg2rad(a), 1, 1, RS_Vector(0.0, 0.0), NULL, RS2::NoUpdate); ins = new RS_Insert(graphic, insData); ins->setLayerToActive(); ins->setPen(RS_Pen(RS_Color(0, 0, 255), RS2::Width05, RS2::SolidLine)); ins->update(); graphic->addEntity(ins); } // insert an array of yellow instances of the block: insData = RS_InsertData("debugblock", RS_Vector(-100.0,-100.0), RS_Vector(0.2,0.2), M_PI/6.0, 6, 4, RS_Vector(100.0, 100.0), NULL, RS2::NoUpdate); ins = new RS_Insert(graphic, insData); ins->setLayerToActive(); ins->setPen(RS_Pen(RS_Color(255, 255, 0), RS2::Width01, RS2::SolidLine)); ins->update(); graphic->addEntity(ins); RS_GraphicView* v = appWin->getGraphicView(); if (v) { v->redraw(); } } RS_DEBUG->print("%s\n: end\n", __func__); }
RS_Entity* RS_Arc::clone() const { RS_Arc* a = new RS_Arc(*this); a->initId(); return a; }