/*************************************************************************** * Copyright (c) 2013 Werner Mayer * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "ui_TaskSketcherValidation.h" #include "TaskSketcherValidation.h" #include #include #include #include #include #include #include #include using namespace SketcherGui; using namespace Gui::TaskView; /* TRANSLATOR SketcherGui::SketcherValidation */ SketcherValidation::SketcherValidation(Sketcher::SketchObject* Obj, QWidget* parent) : QWidget(parent), ui(new Ui_TaskSketcherValidation()), sketch(Obj), sketchAnalyser(Obj), coincidenceRoot(nullptr) { ui->setupUi(this); ui->fixButton->setEnabled(false); ui->fixConstraint->setEnabled(false); ui->swapReversed->setEnabled(false); ui->checkBoxIgnoreConstruction->setEnabled(true); double tolerances[8] = { Precision::Confusion() / 100, Precision::Confusion() / 10, Precision::Confusion(), Precision::Confusion() * 10, Precision::Confusion() * 100, Precision::Confusion() * 1000, Precision::Confusion() * 10000, Precision::Confusion() * 100000 }; QLocale loc; for (int i=0; i<8; i++) { ui->comboBoxTolerance->addItem(loc.toString(tolerances[i]), QVariant(tolerances[i])); } ui->comboBoxTolerance->setCurrentIndex(5); ui->comboBoxTolerance->setEditable(true); ui->comboBoxTolerance->setValidator(new QDoubleValidator(0,10,10,this)); } SketcherValidation::~SketcherValidation() { hidePoints(); } void SketcherValidation::changeEvent(QEvent *e) { if (e->type() == QEvent::LanguageChange) { ui->retranslateUi(this); } QWidget::changeEvent(e); } void SketcherValidation::on_findButton_clicked() { if (sketch.expired()) return; double prec = Precision::Confusion(); bool ok; double conv; conv = QLocale::system().toDouble(ui->comboBoxTolerance->currentText(),&ok); if(ok) { prec = conv; } else { QVariant v = ui->comboBoxTolerance->itemData(ui->comboBoxTolerance->currentIndex()); if (v.isValid()) { prec = v.toDouble(); } } sketchAnalyser.detectMissingPointOnPointConstraints(prec,!ui->checkBoxIgnoreConstruction->isChecked()); std::vector & vertexConstraints = sketchAnalyser.getMissingPointOnPointConstraints(); std::vector points; points.reserve(vertexConstraints.size()); for (auto vc : vertexConstraints) { points.push_back(vc.v); } hidePoints(); if (vertexConstraints.empty()) { QMessageBox::information(this, tr("No missing coincidences"), tr("No missing coincidences found")); ui->fixButton->setEnabled(false); } else { showPoints(points); QMessageBox::warning(this, tr("Missing coincidences"), tr("%1 missing coincidences found").arg(vertexConstraints.size())); ui->fixButton->setEnabled(true); } } void SketcherValidation::on_fixButton_clicked() { if (sketch.expired()) return; // undo command open App::Document* doc = sketch->getDocument(); doc->openTransaction("add coincident constraint"); sketchAnalyser.makeMissingPointOnPointCoincident(); ui->fixButton->setEnabled(false); hidePoints(); // finish the transaction and update Gui::WaitCursor wc; doc->commitTransaction(); doc->recompute(); } void SketcherValidation::on_highlightButton_clicked() { if (sketch.expired()) return; std::vector points; points = sketchAnalyser.getOpenVertices(); hidePoints(); if (!points.empty()) showPoints(points); } void SketcherValidation::on_findConstraint_clicked() { if (sketch.expired()) return; if (sketch->evaluateConstraints()) { QMessageBox::information(this, tr("No invalid constraints"), tr("No invalid constraints found")); ui->fixConstraint->setEnabled(false); } else { QMessageBox::warning(this, tr("Invalid constraints"), tr("Invalid constraints found")); ui->fixConstraint->setEnabled(true); } } void SketcherValidation::on_fixConstraint_clicked() { if (sketch.expired()) return; sketch->validateConstraints(); ui->fixConstraint->setEnabled(false); } void SketcherValidation::on_findReversed_clicked() { if (sketch.expired()) return; std::vector points; const std::vector& geom = sketch->getExternalGeometry(); for (std::size_t i=0; igetTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { const Part::GeomArcOfCircle *segm = static_cast(g); if (segm->isReversed()) { points.push_back(segm->getStartPoint(/*emulateCCW=*/true)); points.push_back(segm->getEndPoint(/*emulateCCW=*/true)); } } } hidePoints(); if(!points.empty()){ int nc = sketch->port_reversedExternalArcs(/*justAnalyze=*/true); showPoints(points); if(nc>0){ QMessageBox::warning(this, tr("Reversed external geometry"), tr("%1 reversed external-geometry arcs were found. Their endpoints are" " encircled in 3d view.\n\n" "%2 constraints are linking to the endpoints. The constraints have" " been listed in Report view (menu View -> Panels -> Report view).\n\n" "Click \"Swap endpoints in constraints\" button to reassign endpoints." " Do this only once to sketches created in FreeCAD older than v0.15" ).arg(points.size()/2).arg(nc) ); ui->swapReversed->setEnabled(true); } else { QMessageBox::warning(this, tr("Reversed external geometry"), tr("%1 reversed external-geometry arcs were found. Their endpoints are " "encircled in 3d view.\n\n" "However, no constraints linking to the endpoints were found.").arg(points.size()/2)); ui->swapReversed->setEnabled(false); } } else { QMessageBox::information(this, tr("Reversed external geometry"), tr("No reversed external-geometry arcs were found.")); } } void SketcherValidation::on_swapReversed_clicked() { if (sketch.expired()) return; App::Document* doc = sketch->getDocument(); doc->openTransaction("Sketch porting"); int n = sketch->port_reversedExternalArcs(/*justAnalyze=*/false); QMessageBox::warning(this, tr("Reversed external geometry"), tr("%1 changes were made to constraints linking to endpoints of reversed arcs.").arg(n)); hidePoints(); ui->swapReversed->setEnabled(false); doc->commitTransaction(); } void SketcherValidation::on_orientLockEnable_clicked() { if (sketch.expired()) return; App::Document* doc = sketch->getDocument(); doc->openTransaction("Constraint orientation lock"); int n = sketch->changeConstraintsLocking(/*bLock=*/true); QMessageBox::warning(this, tr("Constraint orientation locking"), tr("Orientation locking was enabled and recomputed for %1 constraints. The" " constraints have been listed in Report view (menu View -> Panels ->" " Report view).").arg(n)); doc->commitTransaction(); } void SketcherValidation::on_orientLockDisable_clicked() { if (sketch.expired()) return; App::Document* doc = sketch->getDocument(); doc->openTransaction("Constraint orientation unlock"); int n = sketch->changeConstraintsLocking(/*bLock=*/false); QMessageBox::warning(this, tr("Constraint orientation locking"), tr("Orientation locking was disabled for %1 constraints. The" " constraints have been listed in Report view (menu View -> Panels ->" " Report view). Note that for all future constraints, the locking still" " defaults to ON.").arg(n)); doc->commitTransaction(); } void SketcherValidation::on_delConstrExtr_clicked() { if (sketch.expired()) return; int reply; reply = QMessageBox::question(this, tr("Delete constraints to external geom."), tr("You are about to delete ALL constraints that deal with external geometry. This is useful to rescue a sketch with broken/changed links to external geometry. Are you sure you want to delete the constraints?"), QMessageBox::No|QMessageBox::Yes,QMessageBox::No); if(reply!=QMessageBox::Yes) return; App::Document* doc = sketch->getDocument(); doc->openTransaction("Delete constraints"); sketch->delConstraintsToExternal(); doc->commitTransaction(); QMessageBox::warning(this, tr("Delete constraints to external geom."), tr("All constraints that deal with external geometry were deleted.")); } void SketcherValidation::showPoints(const std::vector& pts) { SoCoordinate3 * coords = new SoCoordinate3(); SoDrawStyle * drawStyle = new SoDrawStyle(); drawStyle->pointSize = 6; SoPointSet* pcPoints = new SoPointSet(); coincidenceRoot = new SoGroup(); coincidenceRoot->addChild(drawStyle); SoSeparator* pointsep = new SoSeparator(); SoBaseColor * basecol = new SoBaseColor(); basecol->rgb.setValue(1.0f, 0.5f, 0.0f); pointsep->addChild(basecol); pointsep->addChild(coords); pointsep->addChild(pcPoints); coincidenceRoot->addChild(pointsep); // Draw markers SoBaseColor * markcol = new SoBaseColor(); markcol->rgb.setValue(1.0f, 1.0f, 0.0f); SoMarkerSet* marker = new SoMarkerSet(); marker->markerIndex=Gui::Inventor::MarkerBitmaps::getMarkerIndex("PLUS", App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/View")->GetInt("MarkerSize", 9)); pointsep->addChild(markcol); pointsep->addChild(marker); int pts_size = (int)pts.size(); coords->point.setNum(pts_size); SbVec3f* c = coords->point.startEditing(); for (int i = 0; i < pts_size; i++) { const Base::Vector3d& v = pts[i]; c[i].setValue((float)v.x,(float)v.y,(float)v.z); } coords->point.finishEditing(); if (!sketch.expired()) { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(sketch.get()); vp->getRoot()->addChild(coincidenceRoot); } } void SketcherValidation::hidePoints() { if (coincidenceRoot) { if (!sketch.expired()) { Gui::ViewProvider* vp = Gui::Application::Instance->getViewProvider(sketch.get()); vp->getRoot()->removeChild(coincidenceRoot); } coincidenceRoot = nullptr; } } void SketcherValidation::on_findDegenerated_clicked() { if (sketch.expired()) return; double prec = Precision::Confusion(); int count = sketchAnalyser.detectDegeneratedGeometries(prec); if (count == 0) { QMessageBox::information(this, tr("No degenerated geometry"), tr("No degenerated geometry found")); ui->fixDegenerated->setEnabled(false); } else { QMessageBox::warning(this, tr("Degenerated geometry"), tr("%1 degenerated geometry found").arg(count)); ui->fixDegenerated->setEnabled(true); } } void SketcherValidation::on_fixDegenerated_clicked() { if (sketch.expired()) return; // undo command open App::Document* doc = sketch->getDocument(); doc->openTransaction("Remove degenerated geometry"); double prec = Precision::Confusion(); sketchAnalyser.removeDegeneratedGeometries(prec); ui->fixButton->setEnabled(false); hidePoints(); // finish the transaction and update Gui::WaitCursor wc; doc->commitTransaction(); doc->recompute(); } // ----------------------------------------------- TaskSketcherValidation::TaskSketcherValidation(Sketcher::SketchObject* Obj) { QWidget* widget = new SketcherValidation(Obj); Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox( QPixmap(), widget->windowTitle(), true, nullptr); taskbox->groupLayout()->addWidget(widget); Content.push_back(taskbox); } TaskSketcherValidation::~TaskSketcherValidation() { } #include "moc_TaskSketcherValidation.cpp"