Sketcher: Sketch autoscale (#21084)

* Working scale prototype

* Call viewAll to fit geometries in the viewport post-scaling

* Exclude angle dimensions

* Scale the viewport rather than calling viewAll

* Scale dimension annotation along geometries

* Early return when counting more than one dimensional constraint

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Disable sketch autoscale if there are external geometries in the sketch

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add a setting to disable the feature _ and eventually parametrize

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Check for objects in the viewport in the sketch's ancestry to decide wheter or not to autoscale

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* More consistent camera scaling

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Check for visual indicator in the whole document

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Find visible items in nested assemblies

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Check visual elements in assemblies nested in assemblies

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Set the dimension even if the scaling fails

* Allow constraints that interact with the origin axis/root

* Remove unused variable

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Misc fixes from review

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
theo-vt
2025-06-09 12:31:44 -04:00
committed by GitHub
parent 83b2027395
commit be24c6bbf3
17 changed files with 398 additions and 70 deletions

View File

@@ -37,14 +37,20 @@
#include <Gui/Notifications.h>
#include <Gui/View3DInventor.h>
#include <Gui/View3DInventorViewer.h>
#include <Gui/Document.h>
#include <Mod/Sketcher/App/GeometryFacade.h>
#include <Mod/Sketcher/App/SketchObject.h>
#include <App/Datums.h>
#include "EditDatumDialog.h"
#include "CommandSketcherTools.h"
#include "Utils.h"
#include "ViewProviderSketch.h"
#include "SketcherSettings.h"
#include "ui_InsertDatum.h"
#include <numeric>
using namespace SketcherGui;
@@ -222,6 +228,9 @@ void EditDatumDialog::accepted()
else {
auto unitString = newQuant.getUnit().getString();
unitString = Base::Tools::escapeQuotesFromString(unitString);
performAutoScale(newDatum);
Gui::cmdAppObjectArgs(sketch,
"setDatum(%i,App.Units.Quantity('%f %s'))",
ConstrNbr,
@@ -318,4 +327,102 @@ void EditDatumDialog::formEditorOpened(bool state)
}
}
// This function checks an object's visible flag recursively in a Gui::Document
// assuming that lastParent (if provided) is visible
bool isVisibleUpTo(App::DocumentObject* obj, Gui::Document* doc, App::DocumentObject* lastParent)
{
while (obj && obj != lastParent) {
auto parentviewprovider = doc->getViewProvider(obj);
if (!parentviewprovider || !parentviewprovider->isVisible()) {
return false;
}
obj = obj->getFirstParent();
}
return true;
}
bool hasVisualFeature(App::DocumentObject* obj, App::DocumentObject* rootObj, Gui::Document* doc)
{
auto docObjects = doc->getDocument()->getObjects();
for (auto object : docObjects) {
// Presumably, the sketch that is being edited has visual features, but
// that's not interesting
if (object == obj) {
continue;
}
// No need to continue analysis if the object's visible flag is down
bool visible = isVisibleUpTo(object, doc, rootObj);
if (!visible) {
continue;
}
App::DocumentObject* link = object->getLinkedObject();
if (link->getDocument() != doc->getDocument()) {
Gui::Document* linkDoc = Gui::Application::Instance->getDocument(link->getDocument());
if (linkDoc && hasVisualFeature(link, link, linkDoc)) {
return true;
}
continue;
}
// Skip objects that are not of geometric nature
if (!object->isDerivedFrom<App::GeoFeature>()) {
continue;
}
// Skip datum objects
if (object->isDerivedFrom<App::DatumElement>()) {
continue;
}
// Skip container objects because getting their bounging box might
// return a valid bounding box around annotations or datums
if (object->hasExtension(App::GeoFeatureGroupExtension::getExtensionClassTypeId())) {
continue;
}
// Get the bounding box of the object
auto viewProvider = doc->getViewProvider(object);
if (viewProvider && viewProvider->getBoundingBox().IsValid()) {
return true;
}
}
return false;
}
void EditDatumDialog::performAutoScale(double newDatum)
{
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Sketcher/dimensioning");
long autoScaleMode =
hGrp->GetInt("AutoScaleMode", static_cast<int>(SketcherGui::AutoScaleMode::Always));
// There is a single constraint in the sketch so it can
// be used as a reference to scale the geometries around the origin
// if there are external geometries, it is safe to assume that the sketch
// was drawn with these geometries as scale references (use <= 2 because
// the sketch axis are considered as external geometries)
if ((autoScaleMode == static_cast<int>(SketcherGui::AutoScaleMode::Always)
|| (autoScaleMode
== static_cast<int>(SketcherGui::AutoScaleMode::WhenNoScaleFeatureIsVisible)
&& !hasVisualFeature(sketch, nullptr, Gui::Application::Instance->activeDocument())))
&& sketch->getExternalGeometryCount() <= 2 && sketch->hasSingleScaleDefiningConstraint()) {
try {
double oldDatum = sketch->getDatum(ConstrNbr);
double scale_factor = newDatum / oldDatum;
float initLabelDistance = sketch->Constraints[ConstrNbr]->LabelDistance;
float initLabelPosition = sketch->Constraints[ConstrNbr]->LabelPosition;
centerScale(sketch, scale_factor);
sketch->setLabelDistance(ConstrNbr, initLabelDistance * scale_factor);
sketch->setLabelPosition(ConstrNbr, initLabelPosition * scale_factor);
}
catch (const Base::Exception& e) {
Base::Console().error("Exception performing autoscale: %s\n", e.what());
}
}
}
#include "moc_EditDatumDialog.cpp"