From 13406a4daf744aced2b189b37200a55861fcbd1e Mon Sep 17 00:00:00 2001 From: DeepSOIC Date: Sun, 25 Jan 2015 00:30:49 +0300 Subject: [PATCH] Sketch:Validation: swap endpoints for reversed + constraint orientation locking controls Added buttons to port sketches to CCW-emulation Sketcher. Bonus =) : Added constraint orientation lock/unlock buttons (affects point-wise modes of tangent and perpendicular constraints so far) --- src/Mod/Sketcher/App/SketchObject.cpp | 88 +++++++++++++- src/Mod/Sketcher/App/SketchObject.h | 3 + .../Sketcher/Gui/TaskSketcherValidation.cpp | 107 ++++++++++++++++++ src/Mod/Sketcher/Gui/TaskSketcherValidation.h | 6 + .../Sketcher/Gui/TaskSketcherValidation.ui | 71 ++++++++++-- 5 files changed, 265 insertions(+), 10 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 9c4d79282..7572f17a1 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -1756,7 +1756,11 @@ int SketchObject::delConstraintsToExternal() int GeoId = -3, NullId = -2000; for (std::vector::const_iterator it = constraints.begin(); it != constraints.end(); ++it) { - if ((*it)->First > GeoId && ((*it)->Second > GeoId || (*it)->Second == NullId) && ((*it)->Third > GeoId || (*it)->Third == NullId)) { + if ( (*it)->First > GeoId + && + ((*it)->Second > GeoId || (*it)->Second == NullId) + && + ((*it)->Third > GeoId || (*it)->Third == NullId)) { newConstraints.push_back(*it); } } @@ -2510,6 +2514,8 @@ int SketchObject::changeConstraintsLocking(bool bLock) if (ret) cntSuccess++; tbd.push_back(constNew); newVals[i] = constNew; + Base::Console().Log("Constraint%i will be affected\n", + i+1); } } @@ -2526,6 +2532,86 @@ int SketchObject::changeConstraintsLocking(bool bLock) return cntSuccess; } + +/*! + * \brief SketchObject::port_reversedExternalArcs finds constraints that link to endpoints of external-geometry arcs, and swaps the endpoints in the constraints. This is needed after CCW emulation was introduced, to port old sketches. + * \param justAnalyze if true, nothing is actually done - only the number of constraints to be affected is returned. + * \return the number of constraints changed/to be changed. + */ +int SketchObject::port_reversedExternalArcs(bool justAnalyze) +{ + int cntSuccess = 0; + int cntToBeAffected = 0;//==cntSuccess+cntFail + const std::vector< Constraint * > &vals = this->Constraints.getValues(); + + std::vector< Constraint * > newVals(vals);//modifiable copy of pointers array + + std::vector< Constraint * > tbd;//list of temporary Constraint copies that need to be deleted later + + for(int ic = 0; icFirst; posId = newVals[ic]->FirstPos; break; + case 2: geoId=newVals[ic]->Second; posId = newVals[ic]->SecondPos; break; + case 3: geoId=newVals[ic]->Third; posId = newVals[ic]->ThirdPos; break; + } + + if ( geoId <= -3 && + (posId==Sketcher::start || posId==Sketcher::end)){ + //we are dealing with a link to an endpoint of external geom + Part::Geometry* g = this->ExternalGeo[-geoId-1]; + if (g->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){ + const Part::GeomArcOfCircle *segm = dynamic_cast(g); + if(segm->isReversedInXY()){ + //Gotcha! a link to an endpoint of external arc that is reversed. + //create a constraint copy, affect it, replace the pointer + if (!affected) + constNew = newVals[ic]->clone(); + affected=true; + //Do the fix on temp vars + if(posId == Sketcher::start) + posId = Sketcher::end; + else if (posId == Sketcher::end) + posId = Sketcher::start; + } + } + } + if (!affected) continue; + //Propagate the fix made on temp vars to the constraint + switch (ig){ + case 1: constNew->First = geoId; constNew->FirstPos = posId; break; + case 2: constNew->Second = geoId; constNew->SecondPos = posId; break; + case 3: constNew->Third = geoId; constNew->ThirdPos = posId; break; + } + } + if (affected){ + cntToBeAffected++; + tbd.push_back(constNew); + newVals[ic] = constNew; + Base::Console().Log("Constraint%i will be affected\n", + ic+1); + }; + } + + if(!justAnalyze){ + this->Constraints.setValues(newVals); + Base::Console().Log("Swapped start/end of reversed external arcs in %i constraints\n", + cntToBeAffected); + } + + //clean up - delete temporary copies of constraints that were made to affect the constraints + for(int i=0; isetupUi(this); ui->fixButton->setEnabled(false); ui->fixConstraint->setEnabled(false); + ui->swapReversed->setEnabled(false); double tolerances[8] = { Precision::Confusion() / 100, Precision::Confusion() / 10, @@ -337,6 +338,112 @@ void SketcherValidation::on_fixConstraint_clicked() ui->fixConstraint->setEnabled(false); } +void SketcherValidation::on_findReversed_clicked() +{ + std::vector points; + const std::vector& geom = sketch->getExternalGeometry(); + for (std::size_t i=0; igetTypeId() == Part::GeomArcOfCircle::getClassTypeId()) { + const Part::GeomArcOfCircle *segm = dynamic_cast(g); + if(segm->isReversedInXY()){ + points.push_back(segm->getStartPoint(/*emulateCCW=*/true)); + points.push_back(segm->getEndPoint(/*emulateCCW=*/true)); + } + } + } + hidePoints(); + if(points.size()>0){ + 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 -> Views -> 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::warning(this, tr("Reversed external geometry"), + tr("No reversed external-geometry arcs were found.")); + } +} + +void SketcherValidation::on_swapReversed_clicked() +{ + 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() +{ + 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 -> Views ->" + " Report view).").arg(n)); + + doc->commitTransaction(); +} + +void SketcherValidation::on_orientLockDisable_clicked() +{ + 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 -> Views ->" + " Report view). Note that for all future constraints, the locking still" + " defaults to ON.").arg(n)); + + doc->commitTransaction(); +} + +void SketcherValidation::on_delConstrExtr_clicked() +{ + 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(); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.h b/src/Mod/Sketcher/Gui/TaskSketcherValidation.h index ec175f292..aad1f06a1 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.h @@ -51,6 +51,11 @@ private Q_SLOTS: void on_fixButton_clicked(); void on_findConstraint_clicked(); void on_fixConstraint_clicked(); + void on_findReversed_clicked(); + void on_swapReversed_clicked(); + void on_orientLockEnable_clicked(); + void on_orientLockDisable_clicked(); + void on_delConstrExtr_clicked(); private: void showPoints(const std::vector&); @@ -67,6 +72,7 @@ private: struct ConstraintIds; struct Constraint_Less; std::vector vertexConstraints; + }; class TaskSketcherValidation : public Gui::TaskView::TaskDialog diff --git a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui index 366f01eb5..a303939b1 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherValidation.ui @@ -7,13 +7,43 @@ 0 0 242 - 192 + 423 Sketcher validation + + + + Invalid constraints + + + + + + Fix + + + + + + + Find + + + + + + + Delete constraints to external geom. + + + + + + @@ -47,23 +77,46 @@ - - + + - Invalid constraints + Reversed external geometry - + - + Find - - + + - Fix + Swap endpoints in constraints + + + + + + + + + + Constraint orientation locking + + + + + + Enable/Update + + + + + + + Disable