Skip to content

Commit

Permalink
Sketch:Validation: swap endpoints for reversed + constraint orientati…
Browse files Browse the repository at this point in the history
…on 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)
  • Loading branch information
DeepSOIC authored and wwmayer committed Feb 17, 2015
1 parent 0767cd3 commit 13406a4
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 10 deletions.
88 changes: 87 additions & 1 deletion src/Mod/Sketcher/App/SketchObject.cpp
Expand Up @@ -1756,7 +1756,11 @@ int SketchObject::delConstraintsToExternal()
int GeoId = -3, NullId = -2000;
for (std::vector<Constraint *>::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);
}
}
Expand Down Expand Up @@ -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);
}
}

Expand All @@ -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; ic<newVals.size(); ic++){//ic = index of constraint
bool affected=false;
Constraint *constNew = 0;
for(int ig=1; ig<=3; ig++){//cycle through constraint.first, second, third
int geoId;
Sketcher::PointPos posId;
switch (ig){
case 1: geoId=newVals[ic]->First; 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<const Part::GeomArcOfCircle*>(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; i<tbd.size(); i++){
delete (tbd[i]);
}


return cntToBeAffected;
}

///Locks tangency/perpendicularity type of such a constraint.
///The constraint passed must be writable (i.e. the one that is not
/// yet in the constraint list).
Expand Down
3 changes: 3 additions & 0 deletions src/Mod/Sketcher/App/SketchObject.h
Expand Up @@ -157,6 +157,9 @@ class SketcherExport SketchObject : public Part::Part2DObject
double calculateConstraintError(int ConstrId);
int changeConstraintsLocking(bool bLock);

///porting functions
int port_reversedExternalArcs(bool justAnalyze);

// from base class
virtual PyObject *getPyObject(void);
virtual unsigned int getMemSize(void) const;
Expand Down
107 changes: 107 additions & 0 deletions src/Mod/Sketcher/Gui/TaskSketcherValidation.cpp
Expand Up @@ -62,6 +62,7 @@ SketcherValidation::SketcherValidation(Sketcher::SketchObject* Obj, QWidget* par
ui->setupUi(this);
ui->fixButton->setEnabled(false);
ui->fixConstraint->setEnabled(false);
ui->swapReversed->setEnabled(false);
double tolerances[8] = {
Precision::Confusion() / 100,
Precision::Confusion() / 10,
Expand Down Expand Up @@ -337,6 +338,112 @@ void SketcherValidation::on_fixConstraint_clicked()
ui->fixConstraint->setEnabled(false);
}

void SketcherValidation::on_findReversed_clicked()
{
std::vector<Base::Vector3d> points;
const std::vector<Part::Geometry *>& geom = sketch->getExternalGeometry();
for (std::size_t i=0; i<geom.size(); i++) {
Part::Geometry* g = geom[i];
//only arcs of circles need to be repaired. Arcs of ellipse were so broken there should be nothing to repair from.
if (g->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()) {
const Part::GeomArcOfCircle *segm = dynamic_cast<const Part::GeomArcOfCircle*>(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<Base::Vector3d>& pts)
{
SoCoordinate3 * coords = new SoCoordinate3();
Expand Down
6 changes: 6 additions & 0 deletions src/Mod/Sketcher/Gui/TaskSketcherValidation.h
Expand Up @@ -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<Base::Vector3d>&);
Expand All @@ -67,6 +72,7 @@ private Q_SLOTS:
struct ConstraintIds;
struct Constraint_Less;
std::vector<ConstraintIds> vertexConstraints;

};

class TaskSketcherValidation : public Gui::TaskView::TaskDialog
Expand Down
71 changes: 62 additions & 9 deletions src/Mod/Sketcher/Gui/TaskSketcherValidation.ui
Expand Up @@ -7,13 +7,43 @@
<x>0</x>
<y>0</y>
<width>242</width>
<height>192</height>
<height>423</height>
</rect>
</property>
<property name="windowTitle">
<string>Sketcher validation</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Invalid constraints</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QPushButton" name="fixConstraint">
<property name="text">
<string>Fix</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="findConstraint">
<property name="text">
<string>Find</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QPushButton" name="delConstrExtr">
<property name="text">
<string>Delete constraints to external geom.</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
Expand Down Expand Up @@ -47,23 +77,46 @@
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<item row="4" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Invalid constraints</string>
<string>Reversed external geometry</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPushButton" name="findConstraint">
<widget class="QPushButton" name="findReversed">
<property name="text">
<string>Find</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="fixConstraint">
<item row="1" column="0">
<widget class="QPushButton" name="swapReversed">
<property name="text">
<string>Fix</string>
<string>Swap endpoints in constraints</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Constraint orientation locking</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QPushButton" name="orientLockEnable">
<property name="text">
<string>Enable/Update</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="orientLockDisable">
<property name="text">
<string>Disable</string>
</property>
</widget>
</item>
Expand Down

0 comments on commit 13406a4

Please sign in to comment.