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)
This commit is contained in:
parent
0767cd35f8
commit
13406a4daf
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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; 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).
|
||||
|
|
|
@ -157,6 +157,9 @@ public:
|
|||
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;
|
||||
|
|
|
@ -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,
|
||||
|
@ -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();
|
||||
|
|
|
@ -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>&);
|
||||
|
@ -67,6 +72,7 @@ private:
|
|||
struct ConstraintIds;
|
||||
struct Constraint_Less;
|
||||
std::vector<ConstraintIds> vertexConstraints;
|
||||
|
||||
};
|
||||
|
||||
class TaskSketcherValidation : public Gui::TaskView::TaskDialog
|
||||
|
|
|
@ -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">
|
||||
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue
Block a user