| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | #include <cmath> |
| | #include <limits> |
| |
|
| | #include <QDoubleValidator> |
| | #include <QSignalBlocker> |
| |
|
| | #include "lc_arcpropertieseditingwidget.h" |
| |
|
| | #include "rs_arc.h" |
| | #include "rs_math.h" |
| | #include "ui_lc_arcpropertieseditingwidget.h" |
| |
|
| | LC_ArcPropertiesEditingWidget::LC_ArcPropertiesEditingWidget(QWidget *parent) |
| | : LC_EntityPropertiesEditorWidget(parent) |
| | , ui(new Ui::LC_ArcPropertiesEditingWidget){ |
| | ui->setupUi(this); |
| |
|
| | |
| | auto coordValidator = new QDoubleValidator(this); |
| | ui->leCenterX->setValidator(coordValidator); |
| | ui->leCenterY->setValidator(coordValidator); |
| | ui->leAngle1->setValidator(coordValidator); |
| | ui->leAngle2->setValidator(coordValidator); |
| |
|
| | auto positiveValidator = new QDoubleValidator(0.0, std::numeric_limits<double>::max(), 10, this); |
| | ui->leRadius->setValidator(positiveValidator); |
| | ui->leDiameter->setValidator(positiveValidator); |
| | ui->leArcLength->setValidator(positiveValidator); |
| | ui->leSweepAngle->setValidator(positiveValidator); |
| | ui->leBulge->setValidator(positiveValidator); |
| |
|
| | connect(ui->leCenterX, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onCenterEditingFinished); |
| | connect(ui->leCenterY, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onCenterEditingFinished); |
| | connect(ui->leRadius, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onRadiusEditingFinished); |
| | connect(ui->leDiameter, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onDiameterEditingFinished); |
| | connect(ui->leArcLength, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onArcLengthEditingFinished); |
| | connect(ui->leSweepAngle, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onSweepAngleEditingFinished); |
| | connect(ui->leBulge, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onBulgeEditingFinished); |
| | connect(ui->leAngle1, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onAngle1EditingFinished); |
| | connect(ui->leAngle2, &QLineEdit::editingFinished, this, &LC_ArcPropertiesEditingWidget::onAngle2EditingFinished); |
| | connect(ui->cbReversed, &QCheckBox::toggled, this, &LC_ArcPropertiesEditingWidget::onReversedToggled); |
| | connect(ui->leRadius, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onRadiusTextChanged); |
| | connect(ui->leDiameter, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onDiameterTextChanged); |
| | connect(ui->leArcLength, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onArcLengthTextChanged); |
| | connect(ui->leSweepAngle, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onSweepAngleTextChanged); |
| | connect(ui->leBulge, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onBulgeTextChanged); |
| | connect(ui->leAngle1, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onAngle1TextChanged); |
| | connect(ui->leAngle2, &QLineEdit::textChanged, this, &LC_ArcPropertiesEditingWidget::onAngle2TextChanged); |
| | } |
| |
|
| | LC_ArcPropertiesEditingWidget::~LC_ArcPropertiesEditingWidget(){ |
| | delete ui; |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::setEntity(RS_Entity* entity) { |
| | m_entity = static_cast<RS_Arc*>(entity); |
| |
|
| | { |
| | QSignalBlocker r(ui->leRadius); |
| | QSignalBlocker d(ui->leDiameter); |
| | toUI(m_entity->getCenter(), ui->leCenterX, ui->leCenterY); |
| | toUIValue(m_entity->getRadius(), ui->leRadius); |
| | toUIValue(m_entity->getRadius() * 2, ui->leDiameter); |
| | toUIValue(RS_Math::rad2deg(RS_Math::correctAngle(m_entity->getAngle1())), ui->leAngle1); |
| | toUIValue(RS_Math::rad2deg(RS_Math::correctAngle(m_entity->getAngle2())), ui->leAngle2); |
| | toUIBool(m_entity->isReversed(), ui->cbReversed); |
| | updateUI(); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onCenterEditingFinished() { |
| | m_entity->setCenter(toWCS(ui->leCenterX, ui->leCenterY, m_entity->getCenter())); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onRadiusEditingFinished() { |
| | double newRadius = RS_Math::eval(ui->leRadius->text(), m_entity->getRadius()); |
| | if (newRadius > 0.0) { |
| | m_entity->setRadius(newRadius); |
| | QSignalBlocker d(ui->leDiameter); |
| | toUIValue(newRadius * 2, ui->leDiameter); |
| | updateUI(); |
| | } else { |
| | |
| | toUIValue(m_entity->getRadius(), ui->leRadius); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onDiameterEditingFinished() { |
| | double newDiameter = RS_Math::eval(ui->leDiameter->text(), m_entity->getRadius() * 2); |
| | double newRadius = newDiameter / 2.0; |
| | if (newRadius > 0.0) { |
| | m_entity->setRadius(newRadius); |
| | QSignalBlocker r(ui->leRadius); |
| | toUIValue(newRadius, ui->leRadius); |
| | updateUI(); |
| | } else { |
| | |
| | toUIValue(m_entity->getRadius() * 2, ui->leDiameter); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onArcLengthEditingFinished() { |
| | double newLength = RS_Math::eval(ui->leArcLength->text(), m_entity->getLength()); |
| | double radius = m_entity->getRadius(); |
| | double maxLength = 2 * M_PI * radius; |
| | if (newLength > 0.0 && newLength <= maxLength) { |
| | double newTheta = newLength / radius; |
| | double sign = m_entity->isReversed() ? -1.0 : 1.0; |
| | double newEndRad = m_entity->getAngle1() + sign * newTheta; |
| | m_entity->setAngle2(newEndRad); |
| | QSignalBlocker a(ui->leAngle2); |
| | toUIValue(RS_Math::rad2deg(RS_Math::correctAngle(newEndRad)), ui->leAngle2); |
| | updateUI(); |
| | } else { |
| | toUIValue(m_entity->getLength(), ui->leArcLength); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onSweepAngleEditingFinished() { |
| | double sweep_deg = RS_Math::eval(ui->leSweepAngle->text(), RS_Math::rad2deg(m_entity->getAngleLength())); |
| | if (sweep_deg > 0.0) { |
| | double sweep_rad = RS_Math::deg2rad(sweep_deg); |
| | double sign = m_entity->isReversed() ? -1.0 : 1.0; |
| | double new_end_rad = m_entity->getAngle1() + sign * sweep_rad; |
| | m_entity->setAngle2(new_end_rad); |
| | QSignalBlocker a(ui->leAngle2); |
| | toUIValue(RS_Math::rad2deg(RS_Math::correctAngle(new_end_rad)), ui->leAngle2); |
| | updateUI(); |
| | } else { |
| | toUIValue(RS_Math::rad2deg(m_entity->getAngleLength()), ui->leSweepAngle); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onBulgeEditingFinished() { |
| | double currentTheta = m_entity->getAngleLength(); |
| | double currentBulge = m_entity->getRadius() * (1 - std::cos(currentTheta / 2.0)); |
| | double newBulge = RS_Math::eval(ui->leBulge->text(), currentBulge); |
| | if (newBulge > 0.0) { |
| | double theta = currentTheta; |
| | if (theta > 0.0 && theta < 2 * M_PI) { |
| | double cos_term = std::cos(theta / 2.0); |
| | if (cos_term < 1.0) { |
| | double newRadius = newBulge / (1 - cos_term); |
| | m_entity->setRadius(newRadius); |
| | QSignalBlocker r(ui->leRadius); |
| | QSignalBlocker d(ui->leDiameter); |
| | toUIValue(newRadius, ui->leRadius); |
| | toUIValue(newRadius * 2, ui->leDiameter); |
| | updateUI(); |
| | } else { |
| | toUIValue(currentBulge, ui->leBulge); |
| | } |
| | } else { |
| | toUIValue(currentBulge, ui->leBulge); |
| | } |
| | } else { |
| | toUIValue(currentBulge, ui->leBulge); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onAngle1EditingFinished() { |
| | double currentStartRad = RS_Math::correctAngle(m_entity->getAngle1()); |
| | double currentStartDeg = RS_Math::rad2deg(currentStartRad); |
| | double deg = RS_Math::eval(ui->leAngle1->text(), currentStartDeg); |
| | double rad = RS_Math::deg2rad(deg); |
| | double correctedRad = RS_Math::correctAngle(rad); |
| | m_entity->setAngle1(correctedRad); |
| | QSignalBlocker a1(ui->leAngle1); |
| | toUIValue(RS_Math::rad2deg(correctedRad), ui->leAngle1); |
| | updateUI(); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onAngle2EditingFinished() { |
| | double currentEndRad = RS_Math::correctAngle(m_entity->getAngle2()); |
| | double currentEndDeg = RS_Math::rad2deg(currentEndRad); |
| | double deg = RS_Math::eval(ui->leAngle2->text(), currentEndDeg); |
| | double rad = RS_Math::deg2rad(deg); |
| | double correctedRad = RS_Math::correctAngle(rad); |
| | m_entity->setAngle2(correctedRad); |
| | QSignalBlocker a2(ui->leAngle2); |
| | toUIValue(RS_Math::rad2deg(correctedRad), ui->leAngle2); |
| | updateUI(); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onReversedToggled([[maybe_unused]]bool checked) { |
| | if (m_entity->isReversed() != ui->cbReversed->isChecked()) { |
| | m_entity->revertDirection(); |
| | QSignalBlocker a1(ui->leAngle1); |
| | QSignalBlocker a2(ui->leAngle2); |
| | double startRad = RS_Math::correctAngle(m_entity->getAngle1()); |
| | toUIValue(RS_Math::rad2deg(startRad), ui->leAngle1); |
| | double endRad = RS_Math::correctAngle(m_entity->getAngle2()); |
| | toUIValue(RS_Math::rad2deg(endRad), ui->leAngle2); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onRadiusTextChanged(const QString &text) { |
| | double value = RS_Math::eval(text, 0.0); |
| | if (value > 0.0) { |
| | QSignalBlocker d(ui->leDiameter); |
| | toUIValue(value * 2, ui->leDiameter); |
| | updateDerivedFields(value, m_entity->getAngleLength()); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onDiameterTextChanged(const QString &text) { |
| | double value = RS_Math::eval(text, 0.0); |
| | if (value > 0.0) { |
| | double newRadius = value / 2.0; |
| | QSignalBlocker r(ui->leRadius); |
| | toUIValue(newRadius, ui->leRadius); |
| | updateDerivedFields(newRadius, m_entity->getAngleLength()); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onArcLengthTextChanged(const QString &text) { |
| | double value = RS_Math::eval(text, 0.0); |
| | if (value > 0.0) { |
| | double radius = m_entity->getRadius(); |
| | double newTheta = value / radius; |
| | QSignalBlocker s(ui->leSweepAngle); |
| | toUIValue(RS_Math::rad2deg(newTheta), ui->leSweepAngle); |
| | double sign = m_entity->isReversed() ? -1.0 : 1.0; |
| | double newEndRad = m_entity->getAngle1() + sign * newTheta; |
| | QSignalBlocker a2(ui->leAngle2); |
| | toUIValue(RS_Math::rad2deg(RS_Math::correctAngle(newEndRad)), ui->leAngle2); |
| | updateDerivedFields(radius, newTheta); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onSweepAngleTextChanged(const QString &text) { |
| | double sweep_deg = RS_Math::eval(text, 0.0); |
| | if (sweep_deg > 0.0) { |
| | double sweep_rad = RS_Math::deg2rad(sweep_deg); |
| | double sign = m_entity->isReversed() ? -1.0 : 1.0; |
| | double new_end_rad = m_entity->getAngle1() + sign * sweep_rad; |
| | QSignalBlocker a2(ui->leAngle2); |
| | toUIValue(RS_Math::rad2deg(RS_Math::correctAngle(new_end_rad)), ui->leAngle2); |
| | double radius = m_entity->getRadius(); |
| | updateDerivedFields(radius, sweep_rad); |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onBulgeTextChanged(const QString &text) { |
| | double value = RS_Math::eval(text, 0.0); |
| | if (value > 0.0) { |
| | double theta = m_entity->getAngleLength(); |
| | if (theta > 0.0 && theta < 2 * M_PI) { |
| | double cos_term = std::cos(theta / 2.0); |
| | if (cos_term < 1.0) { |
| | double newRadius = value / (1 - cos_term); |
| | QSignalBlocker r(ui->leRadius); |
| | QSignalBlocker d(ui->leDiameter); |
| | toUIValue(newRadius, ui->leRadius); |
| | toUIValue(newRadius * 2, ui->leDiameter); |
| | updateDerivedFields(newRadius, theta); |
| | } |
| | } |
| | } |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onAngle1TextChanged(const QString &text) { |
| | double degA1 = RS_Math::eval(text, 0.0); |
| | double radA1 = RS_Math::deg2rad(degA1); |
| | double currentRadA2 = m_entity->getAngle2(); |
| | double newTheta = std::abs(currentRadA2 - radA1); |
| | double radius = m_entity->getRadius(); |
| | updateDerivedFields(radius, newTheta); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::onAngle2TextChanged(const QString &text) { |
| | double degA2 = RS_Math::eval(text, 0.0); |
| | double radA2 = RS_Math::deg2rad(degA2); |
| | double currentRadA1 = m_entity->getAngle1(); |
| | double newTheta = std::abs(radA2 - currentRadA1); |
| | double radius = m_entity->getRadius(); |
| | updateDerivedFields(radius, newTheta); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::setupInteractiveInputWidgets() { |
| | pickPointSetup(ui->wPickPointCenter, "center", ui->leCenterX, ui->leCenterY); |
| | pickDistanceSetup(ui->tbPickRadius, "radius", ui->leRadius); |
| | pickDistanceSetup(ui->tbPickDiameter, "diameter", ui->leDiameter); |
| | pickDistanceSetup(ui->tbPickArcLength, "arcLength", ui->leArcLength); |
| | pickAngleSetup(ui->tbPickSweepAngle, "sweepAngle", ui->leSweepAngle); |
| | pickDistanceSetup(ui->tbPickBulge, "bulge", ui->leBulge); |
| | pickAngleSetup(ui->tbPickStartAngle, "startAngle", ui->leAngle1); |
| | pickAngleSetup(ui->tbPickEndAngle, "endAngle", ui->leAngle2); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::updateDerivedFields(double radius, double theta) { |
| | QSignalBlocker al(ui->leArcLength); |
| | toUIValue(radius * theta, ui->leArcLength); |
| | QSignalBlocker sa(ui->leSweepAngle); |
| | toUIValue(RS_Math::rad2deg(theta), ui->leSweepAngle); |
| | QSignalBlocker b(ui->leBulge); |
| | toUIValue(radius * (1 - std::cos(theta / 2.0)), ui->leBulge); |
| | } |
| |
|
| | void LC_ArcPropertiesEditingWidget::updateUI() { |
| | updateDerivedFields(m_entity->getRadius(), m_entity->getAngleLength()); |
| | } |
| |
|