| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| |
|
| | #include <QFileInfo> |
| |
|
| | #include "lc_quadratic.h" |
| | #include "lc_splinepoints.h" |
| | #include "lc_undosection.h" |
| | #include "rs_arc.h" |
| | #include "rs_block.h" |
| | #include "rs_circle.h" |
| | #include "rs_creation.h" |
| | #include "rs_constructionline.h" |
| | #include "rs_debug.h" |
| | #include "rs_ellipse.h" |
| | #include "rs_entitycontainer.h" |
| | #include "rs_graphic.h" |
| | #include "rs_image.h" |
| | #include "rs_information.h" |
| | #include "rs_insert.h" |
| | #include "rs_line.h" |
| | #include "rs_math.h" |
| | #include "rs_modification.h" |
| | #include "rs_units.h" |
| |
|
| | |
| | namespace { |
| | |
| | |
| | |
| | |
| | |
| | bool isArc(const RS_Entity& entity) { |
| | if (entity.isArc()) { |
| | return true; |
| | } |
| | switch (entity.rtti()) { |
| | case RS2::EntityCircle: |
| | case RS2::EntityEllipse: |
| | case RS2::EntityHyperbola: |
| | case RS2::EntityParabola: |
| | return true; |
| | default: |
| | return false; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_LineData fromLineCoordinate(const RS_Vector& line) { |
| | RS_Vector start = RS_Vector{line}.rotate(-M_PI / 4.); |
| | RS_Vector stop = RS_Vector{line}.rotate(M_PI / 4.); |
| | return {start / (-start.dotP(line)), stop / (-stop.dotP(line))}; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Creation::RS_Creation(RS_EntityContainer* container, |
| | LC_GraphicViewport* viewport, |
| | bool handleUndo): |
| | m_container{container} |
| | ,m_graphic{container?container->getGraphic():nullptr} |
| | ,m_document{container?container->getDocument():nullptr} |
| | ,m_viewport{viewport} |
| | ,handleUndo(handleUndo){ |
| | |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Entity* RS_Creation::createParallelThrough(const RS_Vector& coord, |
| | int number, |
| | RS_Entity* e, |
| | bool symmetric) { |
| | if (e == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | double dist = 0.; |
| |
|
| | if (e->rtti()==RS2::EntityLine) { |
| | auto* l = (RS_Line*)e; |
| | RS_ConstructionLine cl(nullptr,RS_ConstructionLineData(l->getStartpoint(),l->getEndpoint())); |
| | dist = cl.getDistanceToPoint(coord); |
| | } else { |
| | dist = e->getDistanceToPoint(coord); |
| | } |
| |
|
| | if (dist<RS_MAXDOUBLE) { |
| | return createParallel(coord, dist, number, e, symmetric); |
| | } else { |
| | return nullptr; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Entity* RS_Creation::createParallel(const RS_Vector& coord, |
| | double distance, int number, |
| | RS_Entity* e, bool symmetric) { |
| | if (e == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | switch (e->rtti()) { |
| | case RS2::EntityLine: |
| | return createParallelLine(coord, distance, number, static_cast<RS_Line*>(e), symmetric); |
| | case RS2::EntityArc: |
| | return createParallelArc(coord, distance, number, static_cast<RS_Arc*>(e)); |
| | case RS2::EntityCircle: |
| | return createParallelCircle(coord, distance, number, static_cast<RS_Circle*>(e)); |
| | case RS2::EntityParabola: |
| | case RS2::EntitySplinePoints: |
| | return createParallelSplinePoints(coord, distance, number, static_cast<LC_SplinePoints*>(e)); |
| | default: |
| | break; |
| | } |
| |
|
| | return nullptr; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Line* RS_Creation::createParallelLine(const RS_Vector& coord, |
| | double distance, int number, |
| | RS_Line* e, |
| | bool symmetric) { |
| |
|
| | if (e == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | double ang = e->getAngle1() + M_PI_2; |
| | RS_LineData parallelData; |
| | RS_Line* ret = nullptr; |
| |
|
| | LC_UndoSection undo( m_document,m_viewport, handleUndo); |
| | for (int num = 1; num <= number; ++num) { |
| |
|
| | |
| | RS_Vector p1 = RS_Vector::polar(distance*num, ang); |
| | p1 += e->getStartpoint(); |
| | RS_Vector p2 = RS_Vector::polar(distance*num, ang); |
| | p2 += e->getEndpoint(); |
| | RS_Line parallel1{p1, p2}; |
| |
|
| | |
| | p1.setPolar(distance*num, ang+M_PI); |
| | p1 += e->getStartpoint(); |
| | p2.setPolar(distance*num, ang+M_PI); |
| | p2 += e->getEndpoint(); |
| | RS_Line parallel2{p1, p2}; |
| |
|
| | double dist1 = parallel1.getDistanceToPoint(coord); |
| | double dist2 = parallel2.getDistanceToPoint(coord); |
| | double minDist = std::min(dist1, dist2); |
| |
|
| | if (minDist<RS_MAXDOUBLE) { |
| | RS_LineData dataToSkip; |
| | if (dist1 < dist2){ |
| | parallelData = parallel1.getData(); |
| | dataToSkip = parallel2.getData(); |
| | } else { |
| | parallelData = parallel2.getData(); |
| | dataToSkip = parallel1.getData(); |
| | } |
| |
|
| | auto *newLine = new RS_Line{m_container, parallelData}; |
| | if (!ret){ |
| | ret = newLine; |
| | } |
| |
|
| | |
| | setupAndAddEntity(newLine); |
| |
|
| | if (symmetric){ |
| | auto *symmetricLine = new RS_Line{m_container, dataToSkip}; |
| | setupAndAddEntity(symmetricLine); |
| | } |
| | } |
| | } |
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Arc* RS_Creation::createParallelArc(const RS_Vector& coord, |
| | double distance, int number, |
| | RS_Arc* e) { |
| |
|
| | if (e == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | RS_ArcData parallelData{}; |
| | RS_Arc* ret = nullptr; |
| |
|
| | bool inside = (e->getCenter().distanceTo(coord) < e->getRadius()); |
| |
|
| | if (inside) { |
| | distance *= -1; |
| | } |
| |
|
| | for (int num = 1; num <= number; ++num) { |
| | |
| | bool ok = true; |
| | RS_Arc parallel1(nullptr, e->getData()); |
| | parallel1.setRadius(e->getRadius() + distance*num); |
| | if (parallel1.getRadius()<0.0) { |
| | parallel1.setRadius(RS_MAXDOUBLE); |
| | ok = false; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | if (ok) { |
| | |
| | parallelData = parallel1.getData(); |
| | |
| | |
| | |
| |
|
| | LC_UndoSection undo( m_document, m_viewport,handleUndo); |
| | auto* newArc = new RS_Arc(m_container, parallelData); |
| | if (!ret) { |
| | ret = newArc; |
| | } |
| | setupAndAddEntity(newArc); |
| | } |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Circle* RS_Creation::createParallelCircle(const RS_Vector& coord, |
| | double distance, int number, |
| | RS_Circle* e) { |
| | if (e == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | RS_CircleData parallelData{}; |
| | RS_Circle* ret = nullptr; |
| |
|
| | bool inside = (e->getCenter().distanceTo(coord) < e->getRadius()); |
| |
|
| | if (inside) { |
| | distance *= -1; |
| | } |
| |
|
| | for (int num = 1; num <= number; ++num) { |
| |
|
| | |
| | bool ok = true; |
| | RS_Circle parallel1(nullptr, e->getData()); |
| | parallel1.setRadius(e->getRadius() + distance*num); |
| | if (parallel1.getRadius()<0.0) { |
| | parallel1.setRadius(RS_MAXDOUBLE); |
| | ok = false; |
| | } |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| |
|
| | |
| | if (ok) { |
| | |
| | parallelData = parallel1.getData(); |
| | |
| | |
| | |
| |
|
| | LC_UndoSection undo( m_document, m_viewport,handleUndo); |
| | auto newCircle = new RS_Circle(m_container, parallelData); |
| | if (!ret) { |
| | ret = newCircle; |
| | } |
| | setupAndAddEntity(newCircle); |
| | } |
| | } |
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | LC_SplinePoints* RS_Creation::createParallelSplinePoints(const RS_Vector& coord, |
| | double distance, int number, LC_SplinePoints* e){ |
| | if (e == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | LC_SplinePoints *psp = nullptr, *ret = nullptr; |
| |
|
| | LC_UndoSection undo( m_document, m_viewport,handleUndo); |
| | for(int i = 1; i <= number; ++i) { |
| | psp = (LC_SplinePoints*)e->clone(); |
| | psp->offset(coord, i*distance); |
| | psp->setParent(m_container); |
| | if(!ret) ret = psp; |
| | setupAndAddEntity(psp); |
| | } |
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Line* RS_Creation::createBisector(const RS_Vector& coord1, |
| | const RS_Vector& coord2, |
| | double length, |
| | int num, |
| | RS_Line* l1, |
| | RS_Line* l2) { |
| |
|
| | |
| | if (!(l1 != nullptr && l2 != nullptr)) { |
| | return nullptr; |
| | } |
| | if (!(l1->rtti()==RS2::EntityLine && l2->rtti()==RS2::EntityLine)) { |
| | return nullptr; |
| | } |
| |
|
| | |
| | RS_VectorSolutions const& sol = |
| | RS_Information::getIntersection(l1, l2, false); |
| | RS_Vector inters = sol.get(0); |
| | if (!inters.valid) { |
| | return nullptr; |
| | } |
| |
|
| | double angle1 = inters.angleTo(l1->getNearestPointOnEntity(coord1)); |
| | double angle2 = inters.angleTo(l2->getNearestPointOnEntity(coord2)); |
| | double angleDiff = RS_Math::getAngleDifference(angle1, angle2); |
| | if (angleDiff > M_PI) { |
| | angleDiff = angleDiff - 2.*M_PI; |
| | } |
| | RS_Line* ret = nullptr; |
| |
|
| | LC_UndoSection undo( m_document, m_viewport, handleUndo); |
| | for (int n = 1; n <= num; ++n) { |
| | double angle = angle1 + (angleDiff / (num + 1) * n); |
| |
|
| | RS_Vector const& v = RS_Vector::polar(length, angle); |
| |
|
| | auto* newLine = new RS_Line{m_container, inters, inters + v}; |
| | if (ret == nullptr) { |
| | ret = newLine; |
| | } |
| | setupAndAddEntity(newLine); |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | std::unique_ptr<RS_Line> RS_Creation::createLineOrthTan(const RS_Vector& coord, |
| | RS_Line* normal, |
| | RS_Entity* circle, |
| | RS_Vector& alternativeTangent){ |
| |
|
| | |
| | if (!(circle != nullptr && normal != nullptr)) { |
| | return {}; |
| | } |
| | |
| | |
| | RS_Vector const& tangent = circle->getNearestOrthTan(coord,*normal,false); |
| | if (tangent.valid) { |
| | double tangentDirection = circle->getTangentDirection(tangent).angle(); |
| | double normalDirection = normal->getDirection1(); |
| | if (RS_Math::equal(RS_Math::correctAngle0ToPi(tangentDirection - normalDirection), M_PI/2, RS_TOLERANCE_ANGLE)) { |
| | RS_Vector linePoint = normal->getNearestPointOnEntity(tangent, false); |
| | return std::make_unique<RS_Line>(m_container, RS_LineData{linePoint, tangent}); |
| | } |
| | } |
| |
|
| | RS2::EntityType rtti = circle->rtti(); |
| | if (!(circle->isArc())) { |
| | return {}; |
| | } |
| |
|
| | RS_Vector tangentPoint0; |
| | RS_Vector t1; |
| | switch (rtti){ |
| | case RS2::EntityCircle: { |
| | auto *cir = dynamic_cast<RS_Circle *>(circle); |
| | const RS_Vector ¢er = cir->getCenter(); |
| | double radius = cir->getRadius(); |
| | RS_Vector vp0(coord - center); |
| | RS_Vector vp1(normal->getAngle1()); |
| | double d = RS_Vector::dotP(vp0, vp1); |
| | const RS_Vector &ortVector = vp1 * radius; |
| | if (d >= 0.){ |
| | tangentPoint0 = center + ortVector; |
| | t1 = center - ortVector; |
| | } else { |
| | tangentPoint0 = center - ortVector; |
| | t1 = center + ortVector; |
| | } |
| | break; |
| | } |
| | case RS2::EntityArc: { |
| | auto *cir = dynamic_cast<RS_Arc *>(circle); |
| | double angle=normal->getAngle1(); |
| | double radius = cir->getRadius(); |
| | RS_Vector vp = RS_Vector::polar(radius, angle); |
| | std::vector<RS_Vector> sol; |
| | bool onEntity = false; |
| | for (int i = 0; i <= 1; i++) { |
| | if(!onEntity || RS_Math::isAngleBetween(angle,cir->getAngle1(),cir->getAngle2(),cir->isReversed())) { |
| | if (i) { |
| | sol.push_back(- vp); |
| | } |
| | else { |
| | sol.push_back(vp); |
| | } |
| | } |
| | angle=RS_Math::correctAngle(angle+M_PI); |
| | } |
| | const RS_Vector ¢er = cir->getCenter(); |
| | switch(sol.size()) { |
| | case 0: |
| | tangentPoint0 = RS_Vector(false); |
| | [[fallthrough]]; |
| | case 2: |
| | if (RS_Vector::dotP(sol[1], coord - center) > 0.){ |
| | tangentPoint0 = center + sol[1]; |
| | t1 = center + sol[0]; |
| | break; |
| | } |
| | [[fallthrough]]; |
| | default: |
| | tangentPoint0 = center + sol[0]; |
| | t1 = center + sol[1]; |
| | break; |
| | } |
| | break; |
| | } |
| | case RS2::EntityEllipse: { |
| | auto *cir = dynamic_cast<RS_Ellipse *>(circle); |
| | |
| | RS_Vector aV(-cir->getAngle()); |
| | RS_Vector direction = normal->getEndpoint() - normal->getStartpoint(); |
| | direction.rotate(aV); |
| | double ratio = cir->getRatio(); |
| | double angle = direction.scale(RS_Vector(1., ratio)).angle(); |
| | double ra(cir->getMajorRadius()); |
| | direction.set(ra * cos(angle), ratio * ra * sin(angle)); |
| | std::vector<RS_Vector> sol; |
| | bool onEntity = false; |
| | for (int i = 0; i < 2; i++) { |
| | if (!onEntity || |
| | RS_Math::isAngleBetween(angle, cir->getAngle1(), cir->getAngle2(), cir->isReversed())){ |
| | if (i){ |
| | sol.push_back(-direction); |
| | } else { |
| | sol.push_back(direction); |
| | } |
| | } |
| | angle = RS_Math::correctAngle(angle + M_PI); |
| | } |
| | if (sol.size() < 1) { |
| | tangentPoint0 = RS_Vector(false); |
| | } |
| | else { |
| | aV.y *= -1.; |
| | for (auto &v: sol) { |
| | v.rotate(aV); |
| | } |
| | const RS_Vector ¢er = cir->getCenter(); |
| | switch (sol.size()) { |
| | case 0: |
| | tangentPoint0 = RS_Vector(false); |
| | [[fallthrough]]; |
| | case 2: |
| | if (RS_Vector::dotP(sol[1], coord - center) > 0.){ |
| | tangentPoint0 = center + sol[1]; |
| | t1 = center + sol[0]; |
| | break; |
| | } |
| | [[fallthrough]]; |
| | default: |
| | tangentPoint0 = center + sol[0]; |
| | t1 = center + sol[1]; |
| | break; |
| | } |
| | } |
| | break; |
| | } |
| | default: |
| | break; |
| | } |
| |
|
| | alternativeTangent = t1; |
| |
|
| | if(!tangentPoint0.valid) { |
| | return {}; |
| | } |
| | RS_Vector const& vp=normal->getNearestPointOnEntity(tangentPoint0, false); |
| | return std::make_unique<RS_Line>(m_container, vp, tangentPoint0); |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Line* RS_Creation::createTangent1(const RS_Vector& coord, |
| | const RS_Vector& point, |
| | RS_Entity* circle, |
| | RS_Vector& tangentPoint, |
| | RS_Vector& altTangentPoint) { |
| | RS_Line* ret = nullptr; |
| | |
| | if (!(circle != nullptr && point.valid && circle->isAtomic())) { |
| | return nullptr; |
| | } |
| |
|
| | if (isArc(*circle)) { |
| | |
| |
|
| | |
| | LC_Quadratic dualLine{{point.x, point.y, 1.}}; |
| | LC_Quadratic dualCircle = circle->getQuadratic().getDualCurve(); |
| | |
| | RS_VectorSolutions dualSol = LC_Quadratic::getIntersection(dualLine, dualCircle); |
| |
|
| | if (dualSol.empty()) |
| | return nullptr; |
| |
|
| | |
| | auto distCoord = [&coord](const RS_Vector& uv) { |
| | return std::abs(uv.dotP(coord) + 1.); |
| | }; |
| |
|
| | if (dualSol.getNumber() == 2 && distCoord(dualSol[1]) < distCoord(dualSol[0])) |
| | std::swap(dualSol[0], dualSol[1]); |
| | if (dualSol.getNumber() == 2) { |
| | altTangentPoint = circle->dualLineTangentPoint(dualSol[1]); |
| | } |
| | tangentPoint = circle->dualLineTangentPoint(dualSol[0]); |
| |
|
| | |
| | if (tangentPoint == point) { |
| | tangentPoint.move(dualSol[0].rotate(M_PI/2.) * circle->getLength()); |
| | } |
| | LC_UndoSection undo(m_document, m_viewport, handleUndo); |
| | ret = new RS_Line{m_container, {point, tangentPoint}}; |
| | setupAndAddEntity(ret); |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | RS_VectorSolutions sol = circle->getTangentPoint(point); |
| |
|
| | |
| | if (sol.isEmpty() || (sol.getNumber() == 1 && sol[0] == point)){ |
| | return nullptr; |
| | } |
| | RS_Vector const vp2{sol.getClosest(coord)}; |
| | RS_LineData d{}; |
| | if ((vp2 - point).squared() > RS_TOLERANCE2) { |
| | d = {vp2, point}; |
| | } |
| | else { |
| | d = {point + circle->getTangentDirection(point), point}; |
| | } |
| |
|
| | tangentPoint = d.startpoint; |
| | if (sol.getNumber() == 1) { |
| | altTangentPoint = sol[0]; |
| | } |
| | else { |
| | altTangentPoint = (sol[0] == vp2) ? sol[1] : sol[0]; |
| | } |
| |
|
| | |
| | LC_UndoSection undo(m_document, m_viewport, handleUndo); |
| | ret = new RS_Line{m_container, d}; |
| | setupAndAddEntity(ret); |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | std::vector<std::unique_ptr<RS_Line>> RS_Creation::createTangent2( |
| | RS_Entity* circle1, |
| | RS_Entity* circle2) { |
| | |
| | if(! (circle1 != nullptr && circle2 != nullptr)) { |
| | return {}; |
| | } |
| |
|
| | if( !(isArc(*circle1) && isArc(*circle2))) { |
| | return {}; |
| | } |
| |
|
| | |
| | |
| | auto sol = LC_Quadratic::getIntersection(circle1->getQuadratic().getDualCurve(), |
| | circle2->getQuadratic().getDualCurve()); |
| | if (sol.empty()) |
| | return {}; |
| | RS_VectorSolutions sol1; |
| | for (const auto& vp: sol) { |
| | if (!vp.valid) { |
| | continue; |
| | } |
| | if (sol1.empty()) { |
| | sol1.push_back(vp); |
| | } |
| | else if (sol1.getClosestDistance(vp) > RS_TOLERANCE_ANGLE) { |
| | sol1.push_back(vp); |
| | } |
| | } |
| |
|
| | |
| | std::vector<std::unique_ptr<RS_Line>> tangents; |
| | std::transform(sol1.begin(), sol1.end(), std::back_inserter(tangents), |
| | [circle1, circle2](const RS_Vector& line) -> std::unique_ptr<RS_Line> { |
| | auto rsLine = std::make_unique<RS_Line>(nullptr, fromLineCoordinate(line)); |
| | rsLine->setStartpoint(circle1->dualLineTangentPoint(line)); |
| | rsLine->setEndpoint(circle2->dualLineTangentPoint(line)); |
| | if (!(rsLine->getStartpoint().isValid() && rsLine->getEndpoint().isValid())) |
| | return nullptr; |
| | return std::unique_ptr<RS_Line>(std::move(rsLine)); |
| | }); |
| | |
| | tangents.erase(remove_if(tangents.begin(), tangents.end(), [](const std::unique_ptr<RS_Line>& line) { |
| | return line == nullptr; |
| | }), tangents.end()); |
| |
|
| | if (tangents.empty()) { |
| | return {}; |
| | } |
| | return tangents; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | std::unique_ptr<RS_Line> RS_Creation::createLineRelAngle(const RS_Vector& coord, |
| | RS_Entity* entity, |
| | double angle, |
| | double length) { |
| | |
| | if (!(entity && coord)) { |
| | return {}; |
| | } |
| |
|
| | switch (entity->rtti()) { |
| | default: |
| | return {}; |
| | case RS2::EntityArc: |
| | case RS2::EntityCircle: |
| | case RS2::EntityLine: |
| | case RS2::EntityEllipse: |
| | break; |
| | } |
| |
|
| | const RS_Vector vp = entity->getNearestPointOnEntity(coord, false); |
| | double const a1 = angle + entity->getTangentDirection(vp).angle(); |
| | RS_Vector const v1 = RS_Vector::polar(length, a1); |
| | auto ret = std::make_unique<RS_Line>(m_container, coord, coord+v1); |
| | bool addedToUndo = setupAndAddEntity(ret.get()); |
| | if (addedToUndo) { |
| | ret.release(); |
| | return {}; |
| | } |
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Line* RS_Creation::createPolygon(const RS_Vector& center, |
| | const RS_Vector& corner, |
| | int number) { |
| | |
| | if (!center.valid || !corner.valid || number<3) { |
| | return nullptr; |
| | } |
| |
|
| | RS_Line* ret = nullptr; |
| |
|
| | double const r = center.distanceTo(corner); |
| | double const angle0 = center.angleTo(corner); |
| | double const da = 2.*M_PI/number; |
| | LC_UndoSection undo( m_document,m_viewport, handleUndo); |
| | for (int i=0; i < number; ++i) { |
| | auto c0 = center + RS_Vector::polar(r, angle0 + i*da); |
| | auto c1 = center + RS_Vector::polar(r, angle0 + ((i+1)%number)*da); |
| |
|
| | auto* line = new RS_Line{m_container, c0, c1}; |
| | line->setLayerToActive(); |
| | line->setPenToActive(); |
| |
|
| | if (!ret) { |
| | ret = line; |
| | } |
| |
|
| | if (m_container) { |
| | m_container->addEntity(line); |
| | } |
| | undo.addUndoable(line); |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Line* RS_Creation::createPolygon2(const RS_Vector& corner1, |
| | const RS_Vector& corner2, |
| | int number) { |
| | |
| | if (!corner1.valid || !corner2.valid || number<3) { |
| | return nullptr; |
| | } |
| |
|
| | RS_Line* ret = nullptr; |
| |
|
| | LC_UndoSection undo( m_document,m_viewport, handleUndo); |
| | double const len = corner1.distanceTo(corner2); |
| | double const da = 2.*M_PI/number; |
| | double const r = 0.5*len/std::sin(0.5*da); |
| | double const angle1 = corner1.angleTo(corner2); |
| | RS_Vector center = (corner1 + corner2)*0.5; |
| |
|
| | |
| | |
| | center += RS_Vector::polar(0.5*len/tan(0.5*da), angle1 + M_PI_2); |
| | double const angle0 = center.angleTo(corner1); |
| |
|
| |
|
| | for (int i=0; i<number; ++i) { |
| | auto c0 = center + RS_Vector::polar(r, angle0 + i*da); |
| | auto c1 = center + RS_Vector::polar(r, angle0 + ((i+1)%number)*da); |
| |
|
| | auto* line = new RS_Line{m_container, c0, c1}; |
| | line->setLayerToActive(); |
| | line->setPenToActive(); |
| |
|
| | if (!ret) { |
| | ret = line; |
| | } |
| |
|
| | if (m_container) { |
| | m_container->addEntity(line); |
| | } |
| | undo.addUndoable(line); |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Line* RS_Creation::createPolygon3(const RS_Vector& center, |
| | const RS_Vector& tangent, |
| | int number) { |
| | |
| | if (!center.valid || !tangent.valid || number<3) { |
| | return nullptr; |
| | } |
| |
|
| | RS_Line* ret = nullptr; |
| |
|
| | LC_UndoSection undo( m_document, m_viewport,handleUndo); |
| | RS_Vector corner(0, 0); |
| | double angle = 2.*M_PI/number/2.0; |
| | corner.x = tangent.x + (center.y - tangent.y) * tan(angle); |
| | corner.y = tangent.y + (tangent.x - center.x) * tan(angle); |
| |
|
| | double const r = center.distanceTo(corner); |
| | double const angle0 = center.angleTo(corner); |
| | double const da = 2.*M_PI/number; |
| |
|
| | for (int i=0; i < number; ++i) { |
| | auto c0 = center + RS_Vector::polar(r, angle0 + i*da); |
| | auto c1 = center + RS_Vector::polar(r, angle0 + ((i+1)%number)*da); |
| |
|
| | auto* line = new RS_Line{m_container, c0, c1}; |
| | line->setLayerToActive(); |
| | line->setPenToActive(); |
| |
|
| | if (!ret) { |
| | ret = line; |
| | } |
| |
|
| | if (m_container) { |
| | m_container->addEntity(line); |
| | } |
| | undo.addUndoable(line); |
| | } |
| |
|
| | return ret; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | RS_Insert* RS_Creation::createInsert(const RS_InsertData* pdata) { |
| | RS_DEBUG->print("RS_Creation::createInsert"); |
| | LC_UndoSection undo( m_document, m_viewport,handleUndo); |
| | auto ins = new RS_Insert(m_container, *pdata); |
| | |
| | setupAndAddEntity(ins); |
| | RS_DEBUG->print("RS_Creation::createInsert: OK"); |
| | return ins; |
| | } |
| | |
| | |
| | |
| | RS_Image* RS_Creation::createImage(const RS_ImageData* data) { |
| | LC_UndoSection undo( m_document, m_viewport,handleUndo); |
| | auto* img = new RS_Image(m_container, *data); |
| | img->update(); |
| | setupAndAddEntity(img); |
| | return img; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | RS_Block* RS_Creation::createBlock(const RS_BlockData* data, |
| | const RS_Vector& referencePoint, |
| | const bool remove) { |
| |
|
| | |
| | LC_UndoSection undo(m_document, m_viewport,remove); |
| | RS_Block* block; |
| | |
| | if (m_container->rtti() == RS2::EntityBlock) { |
| | block = new RS_Block(m_container->getParent(), RS_BlockData(*data)); |
| | } else { |
| | block = new RS_Block(m_container, RS_BlockData(*data)); |
| | } |
| |
|
| | |
| | for(auto e: *m_container){ |
| | if (e != nullptr && e->isSelected()) { |
| |
|
| | |
| | if (remove) { |
| | e->setSelected(false); |
| | } else { |
| | e->setSelected(false); |
| | } |
| |
|
| | |
| | RS_Entity* c = e->clone(); |
| | c->move(-referencePoint); |
| | block->addEntity(c); |
| |
|
| | if (remove) { |
| | |
| | |
| | e->changeUndoState(); |
| | undo.addUndoable(e); |
| | } |
| | } |
| | } |
| |
|
| | if (m_graphic != nullptr) { |
| | m_graphic->addBlock(block); |
| | } |
| |
|
| | return block; |
| | } |
| |
|
| | |
| | |
| | |
| | RS_Insert* RS_Creation::createLibraryInsert(RS_LibraryInsertData& data) { |
| |
|
| | RS_DEBUG->print("RS_Creation::createLibraryInsert"); |
| |
|
| | RS_Graphic* insertGraphic = data.graphic; |
| | if (insertGraphic == nullptr) { |
| | return nullptr; |
| | } |
| |
|
| | |
| | if (m_graphic != nullptr) { |
| | double uf = RS_Units::convert(1.0, insertGraphic->getUnit(),m_graphic->getUnit()); |
| | insertGraphic->scale(RS_Vector(0.0, 0.0), RS_Vector(uf, uf)); |
| | } |
| | QString insertFileName = QFileInfo(data.file).completeBaseName(); |
| | RS_Modification m(*m_container, m_viewport); |
| | m.paste( RS_PasteData(data.insertionPoint,data.factor, data.angle, true,insertFileName),insertGraphic); |
| |
|
| | RS_DEBUG->print("RS_Creation::createLibraryInsert: OK"); |
| |
|
| | return nullptr; |
| | } |
| |
|
| | bool RS_Creation::setupAndAddEntity(RS_Entity* en) const{ |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | assert(en != nullptr); |
| |
|
| | |
| | |
| | en->setLayerToActive(); |
| | en->setPenToActive(); |
| |
|
| | if (m_container) { |
| | m_container->addEntity(en); |
| | } |
| | |
| | |
| | if (m_viewport != nullptr) { |
| | |
| | LC_UndoSection undo(m_document, m_viewport, handleUndo); |
| | undo.addUndoable(en); |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|