diff --git a/src/Base/Interpreter.cpp b/src/Base/Interpreter.cpp index 52c47168af..f9853c1659 100644 --- a/src/Base/Interpreter.cpp +++ b/src/Base/Interpreter.cpp @@ -125,6 +125,8 @@ void PyException::ReportException () const { if (!_isReported) { _isReported = true; + // set sys.last_vars to make post-mortem debugging work + PySys_SetObject("last_traceback", PP_last_traceback); Base::Console().DeveloperError("pyException","%s%s: %s\n", _stackTrace.c_str(), _errorType.c_str(), what()); } diff --git a/src/Gui/PreferencePages/DlgSettingsNavigation.ui b/src/Gui/PreferencePages/DlgSettingsNavigation.ui index 2e7879bdd9..3902e04e7a 100644 --- a/src/Gui/PreferencePages/DlgSettingsNavigation.ui +++ b/src/Gui/PreferencePages/DlgSettingsNavigation.ui @@ -267,16 +267,16 @@ 1 - 1.0 + 1.0 - 100.0 + 100.0 - 0.5 + 0.5 - 5.0 + 5.0 RotationCenterSize @@ -634,7 +634,7 @@ The value is the diameter of the sphere to fit on the screen. - + Qt::Horizontal diff --git a/src/Gui/SoFCCSysDragger.cpp b/src/Gui/SoFCCSysDragger.cpp index e78fbc11a6..ea828a5aa7 100644 --- a/src/Gui/SoFCCSysDragger.cpp +++ b/src/Gui/SoFCCSysDragger.cpp @@ -87,19 +87,24 @@ SO_KIT_SOURCE(TDragger) void TDragger::initClass() { - SO_KIT_INIT_CLASS(TDragger, SoDragger, "Dragger"); + SO_KIT_INIT_CLASS(TDragger, SoDragger, "Dragger"); } TDragger::TDragger() { SO_KIT_CONSTRUCTOR(TDragger); +#if defined(Q_OS_MAC) + this->ref(); +#endif + SO_KIT_ADD_CATALOG_ENTRY(translatorSwitch, SoSwitch, TRUE, geomSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(translator, SoSeparator, TRUE, translatorSwitch, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(translatorActive, SoSeparator, TRUE, translatorSwitch, "", TRUE); - if (SO_KIT_IS_FIRST_INSTANCE()) + if (SO_KIT_IS_FIRST_INSTANCE()) { buildFirstInstance(); + } SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0)); SO_KIT_ADD_FIELD(translationIncrement, (1.0)); @@ -114,7 +119,7 @@ TDragger::TDragger() this->setPartAsDefault("translator", "CSysDynamics_TDragger_Translator"); this->setPartAsDefault("translatorActive", "CSysDynamics_TDragger_TranslatorActive"); - SoSwitch *sw = SO_GET_ANY_PART(this, "translatorSwitch", SoSwitch); + SoSwitch* sw = SO_GET_ANY_PART(this, "translatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 0); this->addStartCallback(&TDragger::startCB); @@ -143,7 +148,7 @@ TDragger::~TDragger() void TDragger::buildFirstInstance() { - SoGroup *geometryGroup = buildGeometry(); + SoGroup* geometryGroup = buildGeometry(); auto localTranslator = new SoSeparator(); localTranslator->setName("CSysDynamics_TDragger_Translator"); @@ -161,12 +166,12 @@ void TDragger::buildFirstInstance() SoGroup* TDragger::buildGeometry() { - //this builds one leg in the Y+ direction because of default done direction. - //the location anchor for shapes is the center of shape. + // this builds one leg in the Y+ direction because of default done direction. + // the location anchor for shapes is the center of shape. auto root = new SoGroup(); - //cylinder + // cylinder float cylinderHeight = 10.0; float cylinderRadius = 0.1f; auto cylinderSeparator = new SoSeparator(); @@ -185,7 +190,7 @@ SoGroup* TDragger::buildGeometry() cylinder->height.setValue(cylinderHeight); cylinderSeparator->addChild(cylinder); - //cone + // cone float coneBottomRadius = 0.8F; float coneHeight = 2.5; auto coneSeparator = new SoSeparator(); @@ -212,66 +217,68 @@ SoGroup* TDragger::buildGeometry() return root; } -void TDragger::startCB(void *, SoDragger *d) +void TDragger::startCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->dragStart(); } -void TDragger::motionCB(void *, SoDragger *d) +void TDragger::motionCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->drag(); } -void TDragger::finishCB(void *, SoDragger *d) +void TDragger::finishCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->dragFinish(); } -void TDragger::fieldSensorCB(void *f, SoSensor *) +void TDragger::fieldSensorCB(void* f, SoSensor*) { - auto sudoThis = static_cast(f); + auto sudoThis = static_cast(f); - if(!f) - return; + if (!f) { + return; + } - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } -void TDragger::valueChangedCB(void *, SoDragger *d) +void TDragger::valueChangedCB(void*, SoDragger* d) { - auto sudoThis = dynamic_cast(d); + auto sudoThis = dynamic_cast(d); assert(sudoThis); - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft - //all this just to get the translation? + // all this just to get the translation? SbVec3f trans, scaleDummy; SbRotation rotationDummy, scaleOrientationDummy; matrix.getTransform(trans, rotationDummy, scaleDummy, scaleOrientationDummy); sudoThis->fieldSensor.detach(); - if (sudoThis->translation.getValue() != trans) + if (sudoThis->translation.getValue() != trans) { sudoThis->translation = trans; + } sudoThis->fieldSensor.attach(&sudoThis->translation); } void TDragger::dragStart() { - SoSwitch *sw; + SoSwitch* sw; sw = SO_GET_ANY_PART(this, "translatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 1); - //do an initial projection to eliminate discrepancies - //in arrow head pick. we define the arrow in the y+ direction - //and we know local space will be relative to this. so y vector - //line projection will work. + // do an initial projection to eliminate discrepancies + // in arrow head pick. we define the arrow in the y+ direction + // and we know local space will be relative to this. so y vector + // line projection will work. projector.setViewVolume(this->getViewVolume()); projector.setWorkingSpace(this->getLocalToWorldMatrix()); projector.setLine(SbLine(SbVec3f(0.0, 0.0, 0.0), SbVec3f(0.0, 1.0, 0.0))); @@ -295,76 +302,79 @@ void TDragger::drag() SbVec3f startingPoint = getLocalStartingPoint(); SbVec3f localMovement = hitPoint - startingPoint; - //scale the increment to match local space. - float scaledIncrement = static_cast(translationIncrement.getValue()) / autoScaleResult.getValue(); + // scale the increment to match local space. + float scaledIncrement = + static_cast(translationIncrement.getValue()) / autoScaleResult.getValue(); localMovement = roundTranslation(localMovement, scaledIncrement); - //when the movement vector is null either the appendTranslation or - //the setMotionMatrix doesn't work. either way it stops translating - //back to its initial starting point. - if (localMovement.equals(SbVec3f(0.0, 0.0, 0.0), 0.00001f)) - { + // when the movement vector is null either the appendTranslation or + // the setMotionMatrix doesn't work. either way it stops translating + // back to its initial starting point. + if (localMovement.equals(SbVec3f(0.0, 0.0, 0.0), 0.00001f)) { setMotionMatrix(getStartMotionMatrix()); - //don't know why I need the following but if I don't have it - //it won't return to original position. + // don't know why I need the following but if I don't have it + // it won't return to original position. this->valueChanged(); } - else + else { setMotionMatrix(appendTranslation(getStartMotionMatrix(), localMovement)); + } - Base::Quantity quantity( - static_cast(translationIncrementCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length); + Base::Quantity quantity(static_cast(translationIncrementCount.getValue()) + * translationIncrement.getValue(), + Base::Unit::Length); - QString message = QString::fromLatin1("%1 %2") - .arg(QObject::tr("Translation:"), quantity.getUserString()); + QString message = + QString::fromLatin1("%1 %2").arg(QObject::tr("Translation:"), quantity.getUserString()); getMainWindow()->showMessage(message, 3000); } void TDragger::dragFinish() { - SoSwitch *sw; + SoSwitch* sw; sw = SO_GET_ANY_PART(this, "translatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 0); } SbBool TDragger::setUpConnections(SbBool onoff, SbBool doitalways) { - if (!doitalways && this->connectionsSetUp == onoff) - return onoff; + if (!doitalways && this->connectionsSetUp == onoff) { + return onoff; + } - SbBool oldval = this->connectionsSetUp; + SbBool oldval = this->connectionsSetUp; - if (onoff) - { - inherited::setUpConnections(onoff, doitalways); - TDragger::fieldSensorCB(this, nullptr); - if (this->fieldSensor.getAttachedField() != &this->translation) - this->fieldSensor.attach(&this->translation); - } - else - { - if (this->fieldSensor.getAttachedField()) - this->fieldSensor.detach(); - inherited::setUpConnections(onoff, doitalways); - } - this->connectionsSetUp = onoff; - return oldval; + if (onoff) { + inherited::setUpConnections(onoff, doitalways); + TDragger::fieldSensorCB(this, nullptr); + if (this->fieldSensor.getAttachedField() != &this->translation) { + this->fieldSensor.attach(&this->translation); + } + } + else { + if (this->fieldSensor.getAttachedField()) { + this->fieldSensor.detach(); + } + inherited::setUpConnections(onoff, doitalways); + } + this->connectionsSetUp = onoff; + return oldval; } -SbVec3f TDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn) +SbVec3f TDragger::roundTranslation(const SbVec3f& vecIn, float incrementIn) { - //everything is transformed into local space. That means we only have - //worry about the y-value. + // everything is transformed into local space. That means we only have + // worry about the y-value. int yCount = 0; float yValue = vecIn[1]; - if (fabs(yValue) > (incrementIn / 2.0)) - { + if (fabs(yValue) > (incrementIn / 2.0)) { yCount = static_cast(yValue / incrementIn); float remainder = fmod(yValue, incrementIn); - if (remainder >= (incrementIn / 2.0)) + if (remainder >= (incrementIn / 2.0)) { yCount++; + } } translationIncrementCount.setValue(yCount); @@ -382,19 +392,28 @@ SO_KIT_SOURCE(TPlanarDragger) void TPlanarDragger::initClass() { - SO_KIT_INIT_CLASS(TPlanarDragger, SoDragger, "Dragger"); + SO_KIT_INIT_CLASS(TPlanarDragger, SoDragger, "Dragger"); } TPlanarDragger::TPlanarDragger() { SO_KIT_CONSTRUCTOR(TPlanarDragger); +#if defined(Q_OS_MAC) + this->ref(); +#endif SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorSwitch, SoSwitch, TRUE, geomSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(planarTranslator, SoSeparator, TRUE, planarTranslatorSwitch, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorActive, SoSeparator, TRUE, planarTranslatorSwitch, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(planarTranslatorActive, + SoSeparator, + TRUE, + planarTranslatorSwitch, + "", + TRUE); - if (SO_KIT_IS_FIRST_INSTANCE()) + if (SO_KIT_IS_FIRST_INSTANCE()) { buildFirstInstance(); + } SO_KIT_ADD_FIELD(translation, (0.0, 0.0, 0.0)); SO_KIT_ADD_FIELD(translationIncrement, (1.0)); @@ -408,9 +427,10 @@ TPlanarDragger::TPlanarDragger() // first is from 'SO_KIT_CATALOG_ENTRY_HEADER' macro // second is unique name from buildFirstInstance(). this->setPartAsDefault("planarTranslator", "CSysDynamics_TPlanarDragger_Translator"); - this->setPartAsDefault("planarTranslatorActive", "CSysDynamics_TPlanarDragger_TranslatorActive"); + this->setPartAsDefault("planarTranslatorActive", + "CSysDynamics_TPlanarDragger_TranslatorActive"); - SoSwitch *sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); + SoSwitch* sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 0); this->addStartCallback(&TPlanarDragger::startCB); @@ -439,7 +459,7 @@ TPlanarDragger::~TPlanarDragger() void TPlanarDragger::buildFirstInstance() { - SoGroup *geometryGroup = buildGeometry(); + SoGroup* geometryGroup = buildGeometry(); auto localTranslator = new SoSeparator(); localTranslator->setName("CSysDynamics_TPlanarDragger_Translator"); @@ -484,65 +504,68 @@ SoGroup* TPlanarDragger::buildGeometry() return root; } -void TPlanarDragger::startCB(void *, SoDragger *d) +void TPlanarDragger::startCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->dragStart(); } -void TPlanarDragger::motionCB(void *, SoDragger *d) +void TPlanarDragger::motionCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->drag(); } -void TPlanarDragger::finishCB(void *, SoDragger *d) +void TPlanarDragger::finishCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->dragFinish(); } -void TPlanarDragger::fieldSensorCB(void *f, SoSensor *) +void TPlanarDragger::fieldSensorCB(void* f, SoSensor*) { - auto sudoThis = static_cast(f); + auto sudoThis = static_cast(f); - if(!f) - return; + if (!f) { + return; + } - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } -void TPlanarDragger::valueChangedCB(void *, SoDragger *d) +void TPlanarDragger::valueChangedCB(void*, SoDragger* d) { - auto sudoThis = dynamic_cast(d); + auto sudoThis = dynamic_cast(d); assert(sudoThis); - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft - //all this just to get the translation? + // all this just to get the translation? SbVec3f trans, scaleDummy; SbRotation rotationDummy, scaleOrientationDummy; matrix.getTransform(trans, rotationDummy, scaleDummy, scaleOrientationDummy); sudoThis->fieldSensor.detach(); - if (sudoThis->translation.getValue() != trans) + if (sudoThis->translation.getValue() != trans) { sudoThis->translation = trans; + } sudoThis->fieldSensor.attach(&sudoThis->translation); } void TPlanarDragger::dragStart() { - SoSwitch *sw; + SoSwitch* sw; sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 1); projector.setViewVolume(this->getViewVolume()); projector.setWorkingSpace(this->getLocalToWorldMatrix()); - projector.setPlane(SbPlane(SbVec3f(0.0, 0.0, 0.0), SbVec3f(1.0, 0.0, 0.0), SbVec3f(0.0, 1.0, 0.0))); + projector.setPlane( + SbPlane(SbVec3f(0.0, 0.0, 0.0), SbVec3f(1.0, 0.0, 0.0), SbVec3f(0.0, 1.0, 0.0))); SbVec3f hitPoint = projector.project(getNormalizedLocaterPosition()); SbMatrix localToWorld = getLocalToWorldMatrix(); @@ -562,75 +585,81 @@ void TPlanarDragger::drag() SbVec3f startingPoint = getLocalStartingPoint(); SbVec3f localMovement = hitPoint - startingPoint; - //scale the increment to match local space. - float scaledIncrement = static_cast(translationIncrement.getValue()) / autoScaleResult.getValue(); + // scale the increment to match local space. + float scaledIncrement = + static_cast(translationIncrement.getValue()) / autoScaleResult.getValue(); localMovement = roundTranslation(localMovement, scaledIncrement); - //when the movement vector is null either the appendTranslation or - //the setMotionMatrix doesn't work. either way it stops translating - //back to its initial starting point. - if (localMovement.equals(SbVec3f(0.0, 0.0, 0.0), 0.00001f)) - { + // when the movement vector is null either the appendTranslation or + // the setMotionMatrix doesn't work. either way it stops translating + // back to its initial starting point. + if (localMovement.equals(SbVec3f(0.0, 0.0, 0.0), 0.00001f)) { setMotionMatrix(getStartMotionMatrix()); - //don't know why I need the following but if I don't have it - //it won't return to original position. + // don't know why I need the following but if I don't have it + // it won't return to original position. this->valueChanged(); } - else + else { setMotionMatrix(appendTranslation(getStartMotionMatrix(), localMovement)); + } - Base::Quantity quantityX( - static_cast(translationIncrementXCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length); - Base::Quantity quantityY( - static_cast(translationIncrementYCount.getValue()) * translationIncrement.getValue(), Base::Unit::Length); + Base::Quantity quantityX(static_cast(translationIncrementXCount.getValue()) + * translationIncrement.getValue(), + Base::Unit::Length); + Base::Quantity quantityY(static_cast(translationIncrementYCount.getValue()) + * translationIncrement.getValue(), + Base::Unit::Length); QString message = QString::fromLatin1("%1 %2, %3") - .arg(QObject::tr("Translation XY:"), quantityX.getUserString(), quantityY.getUserString()); + .arg(QObject::tr("Translation XY:"), + quantityX.getUserString(), + quantityY.getUserString()); getMainWindow()->showMessage(message, 3000); } void TPlanarDragger::dragFinish() { - SoSwitch *sw; + SoSwitch* sw; sw = SO_GET_ANY_PART(this, "planarTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 0); } SbBool TPlanarDragger::setUpConnections(SbBool onoff, SbBool doitalways) { - if (!doitalways && this->connectionsSetUp == onoff) - return onoff; + if (!doitalways && this->connectionsSetUp == onoff) { + return onoff; + } - SbBool oldval = this->connectionsSetUp; + SbBool oldval = this->connectionsSetUp; - if (onoff) - { - inherited::setUpConnections(onoff, doitalways); - TPlanarDragger::fieldSensorCB(this, nullptr); - if (this->fieldSensor.getAttachedField() != &this->translation) - this->fieldSensor.attach(&this->translation); - } - else - { - if (this->fieldSensor.getAttachedField()) - this->fieldSensor.detach(); - inherited::setUpConnections(onoff, doitalways); - } - this->connectionsSetUp = onoff; - return oldval; + if (onoff) { + inherited::setUpConnections(onoff, doitalways); + TPlanarDragger::fieldSensorCB(this, nullptr); + if (this->fieldSensor.getAttachedField() != &this->translation) { + this->fieldSensor.attach(&this->translation); + } + } + else { + if (this->fieldSensor.getAttachedField()) { + this->fieldSensor.detach(); + } + inherited::setUpConnections(onoff, doitalways); + } + this->connectionsSetUp = onoff; + return oldval; } -SbVec3f TPlanarDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn) +SbVec3f TPlanarDragger::roundTranslation(const SbVec3f& vecIn, float incrementIn) { int xCount = 0; float xValue = vecIn[0]; - if (fabs(xValue) > (incrementIn / 2.0)) - { + if (fabs(xValue) > (incrementIn / 2.0)) { xCount = static_cast(xValue / incrementIn); float remainder = fmod(xValue, incrementIn); - if (remainder >= (incrementIn / 2.0)) + if (remainder >= (incrementIn / 2.0)) { xCount++; + } } translationIncrementXCount.setValue(xCount); @@ -638,12 +667,12 @@ SbVec3f TPlanarDragger::roundTranslation(const SbVec3f &vecIn, float incrementIn int yCount = 0; float yValue = vecIn[1]; - if (fabs(yValue) > (incrementIn / 2.0)) - { + if (fabs(yValue) > (incrementIn / 2.0)) { yCount = static_cast(yValue / incrementIn); float remainder = fmod(yValue, incrementIn); - if (remainder >= (incrementIn / 2.0)) + if (remainder >= (incrementIn / 2.0)) { yCount++; + } } translationIncrementYCount.setValue(yCount); @@ -661,12 +690,15 @@ SO_KIT_SOURCE(RDragger) void RDragger::initClass() { - SO_KIT_INIT_CLASS(RDragger, SoDragger, "Dragger"); + SO_KIT_INIT_CLASS(RDragger, SoDragger, "Dragger"); } RDragger::RDragger() { SO_KIT_CONSTRUCTOR(RDragger); +#if defined(Q_OS_MAC) + this->ref(); +#endif SO_KIT_ADD_CATALOG_ENTRY(rotatorSwitch, SoSwitch, TRUE, geomSeparator, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(rotator, SoSeparator, TRUE, rotatorSwitch, "", TRUE); @@ -674,8 +706,9 @@ RDragger::RDragger() arcRadius = 8.0; - if (SO_KIT_IS_FIRST_INSTANCE()) + if (SO_KIT_IS_FIRST_INSTANCE()) { buildFirstInstance(); + } SO_KIT_ADD_FIELD(rotation, (SbVec3f(0.0, 0.0, 1.0), 0.0)); SO_KIT_ADD_FIELD(rotationIncrement, (M_PI / 8.0)); @@ -689,7 +722,7 @@ RDragger::RDragger() this->setPartAsDefault("rotator", "CSysDynamics_RDragger_Rotator"); this->setPartAsDefault("rotatorActive", "CSysDynamics_RDragger_RotatorActive"); - SoSwitch *sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); + SoSwitch* sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 0); this->addStartCallback(&RDragger::startCB); @@ -718,7 +751,7 @@ RDragger::~RDragger() void RDragger::buildFirstInstance() { - SoGroup *geometryGroup = buildGeometry(); + SoGroup* geometryGroup = buildGeometry(); auto localRotator = new SoSeparator(); localRotator->setName("CSysDynamics_RDragger_Rotator"); @@ -738,7 +771,7 @@ SoGroup* RDragger::buildGeometry() { auto root = new SoGroup(); - //arc + // arc auto coordinates = new SoCoordinate3(); unsigned int segments = 15; @@ -746,8 +779,7 @@ SoGroup* RDragger::buildGeometry() float angleIncrement = static_cast(M_PI / 2.0) / static_cast(segments); SbRotation rotation(SbVec3f(0.0, 0.0, 1.0), angleIncrement); SbVec3f point(arcRadius, 0.0, 0.0); - for (unsigned int index = 0; index <= segments; ++index) - { + for (unsigned int index = 0; index <= segments; ++index) { coordinates->point.set1Value(index, point); rotation.multVec(point, point); } @@ -770,7 +802,7 @@ SoGroup* RDragger::buildGeometry() pickStyle->setOverride(TRUE); root->addChild(pickStyle); - //sphere. + // sphere. SbVec3f origin(1.0, 1.0, 0.0); origin.normalize(); origin *= arcRadius; @@ -785,59 +817,61 @@ SoGroup* RDragger::buildGeometry() return root; } -void RDragger::startCB(void *, SoDragger *d) +void RDragger::startCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->dragStart(); } -void RDragger::motionCB(void *, SoDragger *d) +void RDragger::motionCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->drag(); } -void RDragger::finishCB(void *, SoDragger *d) +void RDragger::finishCB(void*, SoDragger* d) { - auto sudoThis = static_cast(d); + auto sudoThis = static_cast(d); assert(sudoThis); sudoThis->dragFinish(); } -void RDragger::fieldSensorCB(void *f, SoSensor *) +void RDragger::fieldSensorCB(void* f, SoSensor*) { - auto sudoThis = static_cast(f); + auto sudoThis = static_cast(f); - if(!f) - return; + if (!f) { + return; + } - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } -void RDragger::valueChangedCB(void *, SoDragger *d) +void RDragger::valueChangedCB(void*, SoDragger* d) { - auto sudoThis = dynamic_cast(d); + auto sudoThis = dynamic_cast(d); assert(sudoThis); - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft - //all this just to get the translation? + // all this just to get the translation? SbVec3f translationDummy, scaleDummy; SbRotation localRotation, scaleOrientationDummy; matrix.getTransform(translationDummy, localRotation, scaleDummy, scaleOrientationDummy); sudoThis->fieldSensor.detach(); - if (sudoThis->rotation.getValue() != localRotation) + if (sudoThis->rotation.getValue() != localRotation) { sudoThis->rotation = localRotation; + } sudoThis->fieldSensor.attach(&sudoThis->rotation); } void RDragger::dragStart() { - SoSwitch *sw; + SoSwitch* sw; sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 1); @@ -846,8 +880,9 @@ void RDragger::dragStart() projector.setPlane(SbPlane(SbVec3f(0.0, 0.0, 1.0), 0.0)); SbVec3f hitPoint; - if (!projector.tryProject(getNormalizedLocaterPosition(), 0.0, hitPoint)) + if (!projector.tryProject(getNormalizedLocaterPosition(), 0.0, hitPoint)) { return; + } hitPoint.normalize(); SbMatrix localToWorld = getLocalToWorldMatrix(); @@ -863,90 +898,93 @@ void RDragger::drag() projector.setWorkingSpace(this->getLocalToWorldMatrix()); SbVec3f hitPoint; - if (!projector.tryProject(getNormalizedLocaterPosition(), 0.0, hitPoint)) + if (!projector.tryProject(getNormalizedLocaterPosition(), 0.0, hitPoint)) { return; + } hitPoint.normalize(); SbVec3f startingPoint = getLocalStartingPoint(); startingPoint.normalize(); SbRotation localRotation(startingPoint, hitPoint); - //getting some slop from this. grab vector and put it absolute. + // getting some slop from this. grab vector and put it absolute. SbVec3f tempVec; float tempRadians; localRotation.getValue(tempVec, tempRadians); tempVec[0] = 0.0; tempVec[1] = 0.0; tempVec.normalize(); - if (tempVec[2] < 0.0) - { + if (tempVec[2] < 0.0) { tempRadians *= -1.0; tempVec.negate(); } int incrementCount = roundIncrement(tempRadians); rotationIncrementCount.setValue(incrementCount); - localRotation = SbRotation(tempVec, incrementCount * static_cast(rotationIncrement.getValue())); + localRotation = + SbRotation(tempVec, incrementCount * static_cast(rotationIncrement.getValue())); - //same problem as described in tDragger::drag. - if (localRotation.equals(SbRotation(SbVec3f(0.0, 0.0, 1.0), 0.0), 0.00001f)) - { + // same problem as described in tDragger::drag. + if (localRotation.equals(SbRotation(SbVec3f(0.0, 0.0, 1.0), 0.0), 0.00001f)) { setMotionMatrix(getStartMotionMatrix()); this->valueChanged(); } - else - setMotionMatrix(appendRotation(getStartMotionMatrix(), localRotation, SbVec3f(0.0, 0.0, 0.0))); + else { + setMotionMatrix( + appendRotation(getStartMotionMatrix(), localRotation, SbVec3f(0.0, 0.0, 0.0))); + } - Base::Quantity quantity( - static_cast(rotationIncrementCount.getValue()) * (180.0 / M_PI) * - rotationIncrement.getValue(), Base::Unit::Angle); + Base::Quantity quantity(static_cast(rotationIncrementCount.getValue()) * (180.0 / M_PI) + * rotationIncrement.getValue(), + Base::Unit::Angle); - QString message = QString::fromLatin1("%1 %2") - .arg(QObject::tr("Rotation:"), quantity.getUserString()); + QString message = + QString::fromLatin1("%1 %2").arg(QObject::tr("Rotation:"), quantity.getUserString()); getMainWindow()->showMessage(message, 3000); } void RDragger::dragFinish() { - SoSwitch *sw; + SoSwitch* sw; sw = SO_GET_ANY_PART(this, "rotatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, 0); } SbBool RDragger::setUpConnections(SbBool onoff, SbBool doitalways) { - if (!doitalways && this->connectionsSetUp == onoff) - return onoff; + if (!doitalways && this->connectionsSetUp == onoff) { + return onoff; + } - SbBool oldval = this->connectionsSetUp; + SbBool oldval = this->connectionsSetUp; - if (onoff) - { - inherited::setUpConnections(onoff, doitalways); - RDragger::fieldSensorCB(this, nullptr); - if (this->fieldSensor.getAttachedField() != &this->rotation) - this->fieldSensor.attach(&this->rotation); - } - else - { - if (this->fieldSensor.getAttachedField()) - this->fieldSensor.detach(); - inherited::setUpConnections(onoff, doitalways); - } - this->connectionsSetUp = onoff; - return oldval; + if (onoff) { + inherited::setUpConnections(onoff, doitalways); + RDragger::fieldSensorCB(this, nullptr); + if (this->fieldSensor.getAttachedField() != &this->rotation) { + this->fieldSensor.attach(&this->rotation); + } + } + else { + if (this->fieldSensor.getAttachedField()) { + this->fieldSensor.detach(); + } + inherited::setUpConnections(onoff, doitalways); + } + this->connectionsSetUp = onoff; + return oldval; } -int RDragger::roundIncrement(const float &radiansIn) +int RDragger::roundIncrement(const float& radiansIn) { int rCount = 0; auto increment = static_cast(rotationIncrement.getValue()); - if (fabs(radiansIn) > (increment / 2.0)) - { + if (fabs(radiansIn) > (increment / 2.0)) { rCount = static_cast(radiansIn / increment); float remainder = fmod(radiansIn, increment); - if (remainder >= (increment / 2.0)) + if (remainder >= (increment / 2.0)) { rCount++; + } } return rCount; @@ -964,7 +1002,7 @@ void SoFCCSysDragger::initClass() } SoFCCSysDragger::SoFCCSysDragger() - : axisScale(1.0f,1.0f,1.0f) + : axisScale(1.0f, 1.0f, 1.0f) { SO_KIT_CONSTRUCTOR(SoFCCSysDragger); @@ -999,21 +1037,81 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSwitch, SoSwitch, TRUE, annotation, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSeparator, SoSeparator, TRUE, xyPlanarTranslatorSwitch, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSeparator, SoSeparator, TRUE, yzPlanarTranslatorSwitch, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSeparator, SoSeparator, TRUE, zxPlanarTranslatorSwitch, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorSeparator, + SoSeparator, + TRUE, + xyPlanarTranslatorSwitch, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorSeparator, + SoSeparator, + TRUE, + yzPlanarTranslatorSwitch, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorSeparator, + SoSeparator, + TRUE, + zxPlanarTranslatorSwitch, + "", + TRUE); - SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorColor, SoBaseColor, TRUE, xyPlanarTranslatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorColor, SoBaseColor, TRUE, yzPlanarTranslatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorColor, SoBaseColor, TRUE, zxPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorColor, + SoBaseColor, + TRUE, + xyPlanarTranslatorSeparator, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorColor, + SoBaseColor, + TRUE, + yzPlanarTranslatorSeparator, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorColor, + SoBaseColor, + TRUE, + zxPlanarTranslatorSeparator, + "", + TRUE); - SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorRotation, SoRotation, TRUE, xyPlanarTranslatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorRotation, SoRotation, TRUE, yzPlanarTranslatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorRotation, SoRotation, TRUE, zxPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorRotation, + SoRotation, + TRUE, + xyPlanarTranslatorSeparator, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorRotation, + SoRotation, + TRUE, + yzPlanarTranslatorSeparator, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorRotation, + SoRotation, + TRUE, + zxPlanarTranslatorSeparator, + "", + TRUE); - SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorDragger, TPlanarDragger, TRUE, xyPlanarTranslatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorDragger, TPlanarDragger, TRUE, yzPlanarTranslatorSeparator, "", TRUE); - SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorDragger, TPlanarDragger, TRUE, zxPlanarTranslatorSeparator, "", TRUE); + SO_KIT_ADD_CATALOG_ENTRY(xyPlanarTranslatorDragger, + TPlanarDragger, + TRUE, + xyPlanarTranslatorSeparator, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(yzPlanarTranslatorDragger, + TPlanarDragger, + TRUE, + yzPlanarTranslatorSeparator, + "", + TRUE); + SO_KIT_ADD_CATALOG_ENTRY(zxPlanarTranslatorDragger, + TPlanarDragger, + TRUE, + zxPlanarTranslatorSeparator, + "", + TRUE); // Rotator @@ -1057,16 +1155,14 @@ SoFCCSysDragger::SoFCCSysDragger() SO_KIT_INIT_INSTANCE(); // Colors - setAxisColors( - SbColor(1.0, 0, 0).getPackedValue(0.0f), - SbColor(0, 1.0, 0).getPackedValue(0.0f), - SbColor(0, 0, 1.0).getPackedValue(0.0f) - ); + setAxisColors(SbColor(1.0, 0, 0).getPackedValue(0.0f), + SbColor(0, 1.0, 0).getPackedValue(0.0f), + SbColor(0, 0, 1.0).getPackedValue(0.0f)); // Increments // Translator - TDragger *tDragger; + TDragger* tDragger; tDragger = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger); tDragger->translationIncrement.connectFrom(&this->translationIncrement); tDragger->autoScaleResult.connectFrom(&this->autoScaleResult); @@ -1080,7 +1176,7 @@ SoFCCSysDragger::SoFCCSysDragger() tDragger->autoScaleResult.connectFrom(&this->autoScaleResult); translationIncrementCountZ.connectFrom(&tDragger->translationIncrementCount); // Planar Translator - TPlanarDragger *tPlanarDragger; + TPlanarDragger* tPlanarDragger; tPlanarDragger = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger); tPlanarDragger->translationIncrement.connectFrom(&this->translationIncrement); tPlanarDragger->autoScaleResult.connectFrom(&this->autoScaleResult); @@ -1097,7 +1193,7 @@ SoFCCSysDragger::SoFCCSysDragger() translationIncrementCountX.appendConnection(&tPlanarDragger->translationIncrementXCount); translationIncrementCountZ.appendConnection(&tPlanarDragger->translationIncrementYCount); // Rotator - RDragger *rDragger; + RDragger* rDragger; rDragger = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger); rDragger->rotationIncrement.connectFrom(&this->rotationIncrement); rotationIncrementCountX.connectFrom(&rDragger->rotationIncrementCount); @@ -1111,7 +1207,7 @@ SoFCCSysDragger::SoFCCSysDragger() // Switches // Translator - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + SoSwitch* sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); @@ -1134,7 +1230,7 @@ SoFCCSysDragger::SoFCCSysDragger() // Rotations - SoRotation *localRotation; + SoRotation* localRotation; SbRotation tempRotation; auto angle = static_cast(M_PI / 2.0); // Translator @@ -1163,13 +1259,13 @@ SoFCCSysDragger::SoFCCSysDragger() localRotation = SO_GET_ANY_PART(this, "zRotatorRotation", SoRotation); localRotation->rotation.setValue(SbRotation::identity()); - //this is for non-autoscale mode. this will be disconnected for autoscale - //and won't be used. see setUpAutoScale. - auto scaleEngine = new SoComposeVec3f(); //uses coin ref scheme. + // this is for non-autoscale mode. this will be disconnected for autoscale + // and won't be used. see setUpAutoScale. + auto scaleEngine = new SoComposeVec3f(); // uses coin ref scheme. scaleEngine->x.connectFrom(&draggerSize); scaleEngine->y.connectFrom(&draggerSize); scaleEngine->z.connectFrom(&draggerSize); - SoScale *localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); + SoScale* localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); localScaleNode->scaleFactor.connectFrom(&scaleEngine->vector); autoScaleResult.connectFrom(&draggerSize); @@ -1212,21 +1308,24 @@ SoFCCSysDragger::~SoFCCSysDragger() SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways) { - if (!doitalways && (connectionsSetUp == onoff)) + if (!doitalways && (connectionsSetUp == onoff)) { return onoff; + } - TDragger *tDraggerX = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger); - TDragger *tDraggerY = SO_GET_ANY_PART(this, "yTranslatorDragger", TDragger); - TDragger *tDraggerZ = SO_GET_ANY_PART(this, "zTranslatorDragger", TDragger); - TPlanarDragger *tPlanarDraggerXZ = SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger); - TPlanarDragger *tPlanarDraggerYZ = SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", TPlanarDragger); - TPlanarDragger *tPlanarDraggerZX = SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", TPlanarDragger); - RDragger *rDraggerX = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger); - RDragger *rDraggerY = SO_GET_ANY_PART(this, "yRotatorDragger", RDragger); - RDragger *rDraggerZ = SO_GET_ANY_PART(this, "zRotatorDragger", RDragger); + TDragger* tDraggerX = SO_GET_ANY_PART(this, "xTranslatorDragger", TDragger); + TDragger* tDraggerY = SO_GET_ANY_PART(this, "yTranslatorDragger", TDragger); + TDragger* tDraggerZ = SO_GET_ANY_PART(this, "zTranslatorDragger", TDragger); + TPlanarDragger* tPlanarDraggerXZ = + SO_GET_ANY_PART(this, "xyPlanarTranslatorDragger", TPlanarDragger); + TPlanarDragger* tPlanarDraggerYZ = + SO_GET_ANY_PART(this, "yzPlanarTranslatorDragger", TPlanarDragger); + TPlanarDragger* tPlanarDraggerZX = + SO_GET_ANY_PART(this, "zxPlanarTranslatorDragger", TPlanarDragger); + RDragger* rDraggerX = SO_GET_ANY_PART(this, "xRotatorDragger", RDragger); + RDragger* rDraggerY = SO_GET_ANY_PART(this, "yRotatorDragger", RDragger); + RDragger* rDraggerZ = SO_GET_ANY_PART(this, "zRotatorDragger", RDragger); - if (onoff) - { + if (onoff) { inherited::setUpConnections(onoff, doitalways); registerChildDragger(tDraggerX); @@ -1240,15 +1339,16 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways) registerChildDragger(rDraggerZ); translationSensorCB(this, nullptr); - if (this->translationSensor.getAttachedField() != &this->translation) - this->translationSensor.attach(&this->translation); + if (this->translationSensor.getAttachedField() != &this->translation) { + this->translationSensor.attach(&this->translation); + } rotationSensorCB(this, nullptr); - if (this->rotationSensor.getAttachedField() != &this->rotation) + if (this->rotationSensor.getAttachedField() != &this->rotation) { this->rotationSensor.attach(&this->rotation); + } } - else - { + else { unregisterChildDragger(tDraggerX); unregisterChildDragger(tDraggerY); unregisterChildDragger(tDraggerZ); @@ -1261,98 +1361,104 @@ SbBool SoFCCSysDragger::setUpConnections(SbBool onoff, SbBool doitalways) inherited::setUpConnections(onoff, doitalways); - if (this->translationSensor.getAttachedField()) - this->translationSensor.detach(); + if (this->translationSensor.getAttachedField()) { + this->translationSensor.detach(); + } - if (this->rotationSensor.getAttachedField()) + if (this->rotationSensor.getAttachedField()) { this->rotationSensor.detach(); + } } return !(this->connectionsSetUp = onoff); } -void SoFCCSysDragger::translationSensorCB(void *f, SoSensor *) +void SoFCCSysDragger::translationSensorCB(void* f, SoSensor*) { - auto sudoThis = static_cast(f); - if(!f) - return; + auto sudoThis = static_cast(f); + if (!f) { + return; + } - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } -void SoFCCSysDragger::rotationSensorCB(void *f, SoSensor *) +void SoFCCSysDragger::rotationSensorCB(void* f, SoSensor*) { - auto sudoThis = static_cast(f); - if(!f) - return; + auto sudoThis = static_cast(f); + if (!f) { + return; + } - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft sudoThis->workFieldsIntoTransform(matrix); sudoThis->setMotionMatrix(matrix); } -void SoFCCSysDragger::valueChangedCB(void *, SoDragger *d) +void SoFCCSysDragger::valueChangedCB(void*, SoDragger* d) { - auto sudoThis = dynamic_cast(d); + auto sudoThis = dynamic_cast(d); assert(sudoThis); - SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft + SbMatrix matrix = sudoThis->getMotionMatrix(); // clazy:exclude=rule-of-two-soft - //all this just to get the translation? + // all this just to get the translation? SbVec3f localTranslation, scaleDummy; SbRotation localRotation, scaleOrientationDummy; matrix.getTransform(localTranslation, localRotation, scaleDummy, scaleOrientationDummy); sudoThis->translationSensor.detach(); - if (sudoThis->translation.getValue() != localTranslation) + if (sudoThis->translation.getValue() != localTranslation) { sudoThis->translation = localTranslation; + } sudoThis->translationSensor.attach(&sudoThis->translation); sudoThis->rotationSensor.detach(); - if (sudoThis->rotation.getValue() != localRotation) + if (sudoThis->rotation.getValue() != localRotation) { sudoThis->rotation = localRotation; + } sudoThis->rotationSensor.attach(&sudoThis->rotation); } -void SoFCCSysDragger::setUpAutoScale(SoCamera *cameraIn) +void SoFCCSysDragger::setUpAutoScale(SoCamera* cameraIn) { - //note: sofieldsensor checks if the current sensor is already attached - //and takes appropriate action. So it is safe to attach to a field without - //checking current attachment state. - if (cameraIn->getTypeId() == SoOrthographicCamera::getClassTypeId()) - { - auto localCamera = dynamic_cast(cameraIn); + // note: sofieldsensor checks if the current sensor is already attached + // and takes appropriate action. So it is safe to attach to a field without + // checking current attachment state. + if (cameraIn->getTypeId() == SoOrthographicCamera::getClassTypeId()) { + auto localCamera = dynamic_cast(cameraIn); assert(localCamera); cameraSensor.attach(&localCamera->height); - SoScale *localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); + SoScale* localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); localScaleNode->scaleFactor.disconnect(); autoScaleResult.disconnect(&draggerSize); cameraCB(this, nullptr); } - else if (cameraIn->getTypeId() == SoPerspectiveCamera::getClassTypeId()) - { - auto localCamera = dynamic_cast(cameraIn); + else if (cameraIn->getTypeId() == SoPerspectiveCamera::getClassTypeId()) { + auto localCamera = dynamic_cast(cameraIn); assert(localCamera); cameraSensor.attach(&localCamera->position); - SoScale *localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); + SoScale* localScaleNode = SO_GET_ANY_PART(this, "scaleNode", SoScale); localScaleNode->scaleFactor.disconnect(); autoScaleResult.disconnect(&draggerSize); cameraCB(this, nullptr); } } -void SoFCCSysDragger::cameraCB(void *data, SoSensor *) +void SoFCCSysDragger::cameraCB(void* data, SoSensor*) { - auto sudoThis = static_cast(data); - if (!sudoThis) - return; - if (!sudoThis->idleSensor.isScheduled()) + auto sudoThis = static_cast(data); + if (!sudoThis) { + return; + } + if (!sudoThis->idleSensor.isScheduled()) { sudoThis->idleSensor.schedule(); + } } -void SoFCCSysDragger::GLRender(SoGLRenderAction * action) +void SoFCCSysDragger::GLRender(SoGLRenderAction* action) { - if(!scaleInited) { + if (!scaleInited) { scaleInited = true; updateDraggerCache(action->getCurPath()); updateAxisScale(); @@ -1361,24 +1467,25 @@ void SoFCCSysDragger::GLRender(SoGLRenderAction * action) inherited::GLRender(action); } -void SoFCCSysDragger::updateAxisScale() { +void SoFCCSysDragger::updateAxisScale() +{ SbMatrix localToWorld = getLocalToWorldMatrix(); SbVec3f origin; localToWorld.multVecMatrix(SbVec3f(0.0, 0.0, 0.0), origin); - SbVec3f vx,vy,vz; + SbVec3f vx, vy, vz; localToWorld.multVecMatrix(SbVec3f(1.0f, 0.0f, 0.0f), vx); localToWorld.multVecMatrix(SbVec3f(0.0f, 1.0f, 0.0f), vy); localToWorld.multVecMatrix(SbVec3f(0.0f, 0.0f, 1.0f), vz); - float x = std::max((vx-origin).length(),1e-7f); - float y = std::max((vy-origin).length(),1e-7f); - float z = std::max((vz-origin).length(),1e-7f); - if(!axisScale.equals(SbVec3f(x,y,z),1e-7f)) { - axisScale.setValue(x,y,z); - idleCB(this,&idleSensor); + float x = std::max((vx - origin).length(), 1e-7f); + float y = std::max((vy - origin).length(), 1e-7f); + float z = std::max((vz - origin).length(), 1e-7f); + if (!axisScale.equals(SbVec3f(x, y, z), 1e-7f)) { + axisScale.setValue(x, y, z); + idleCB(this, &idleSensor); } } -void SoFCCSysDragger::handleEvent(SoHandleEventAction * action) +void SoFCCSysDragger::handleEvent(SoHandleEventAction* action) { this->ref(); @@ -1388,14 +1495,14 @@ void SoFCCSysDragger::handleEvent(SoHandleEventAction * action) this->unref(); } -void SoFCCSysDragger::idleCB(void *data, SoSensor *) +void SoFCCSysDragger::idleCB(void* data, SoSensor*) { - auto sudoThis = static_cast(data); - if (!data) - return; + auto sudoThis = static_cast(data); + if (!data) { + return; + } SoField* field = sudoThis->cameraSensor.getAttachedField(); - if (field) - { + if (field) { auto camera = static_cast(field->getContainer()); SbMatrix localToWorld = sudoThis->getLocalToWorldMatrix(); SbVec3f origin; @@ -1404,29 +1511,29 @@ void SoFCCSysDragger::idleCB(void *data, SoSensor *) SbViewVolume viewVolume = camera->getViewVolume(); float radius = sudoThis->draggerSize.getValue() / 2.0; float localScale = viewVolume.getWorldToScreenScale(origin, radius); - float sx,sy,sz; - sudoThis->axisScale.getValue(sx,sy,sz); - SbVec3f scaleVector(localScale/sx, localScale/sy, localScale/sz); - SoScale *localScaleNode = SO_GET_ANY_PART(sudoThis, "scaleNode", SoScale); + float sx, sy, sz; + sudoThis->axisScale.getValue(sx, sy, sz); + SbVec3f scaleVector(localScale / sx, localScale / sy, localScale / sz); + SoScale* localScaleNode = SO_GET_ANY_PART(sudoThis, "scaleNode", SoScale); localScaleNode->scaleFactor.setValue(scaleVector); sudoThis->autoScaleResult.setValue(localScale); } } -void SoFCCSysDragger::finishDragCB(void *data, SoDragger *) +void SoFCCSysDragger::finishDragCB(void* data, SoDragger*) { - auto sudoThis = static_cast(data); + auto sudoThis = static_cast(data); assert(sudoThis); // note: when creating a second view of the document and then closing // the first viewer it deletes the camera. However, the attached field // of the cameraSensor will be detached automatically. SoField* field = sudoThis->cameraSensor.getAttachedField(); - if (field) - { + if (field) { auto camera = static_cast(field->getContainer()); - if (camera->getTypeId() == SoPerspectiveCamera::getClassTypeId()) + if (camera->getTypeId() == SoPerspectiveCamera::getClassTypeId()) { cameraCB(sudoThis, nullptr); + } } } @@ -1440,7 +1547,8 @@ void SoFCCSysDragger::clearIncrementCounts() rotationIncrementCountZ.setValue(0); } -void SoFCCSysDragger::setAxisColors(unsigned long x, unsigned long y, unsigned long z) { +void SoFCCSysDragger::setAxisColors(unsigned long x, unsigned long y, unsigned long z) +{ SbColor colorX; SbColor colorY; SbColor colorZ; @@ -1480,194 +1588,194 @@ void SoFCCSysDragger::setAxisColors(unsigned long x, unsigned long y, unsigned l // Translator void SoFCCSysDragger::showTranslationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::showTranslationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::showTranslationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::hideTranslationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoFCCSysDragger::hideTranslationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoFCCSysDragger::hideTranslationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } bool SoFCCSysDragger::isShownTranslationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isShownTranslationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isShownTranslationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isHiddenTranslationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "xTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoFCCSysDragger::isHiddenTranslationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "yTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoFCCSysDragger::isHiddenTranslationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "zTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } // Planar Translator void SoFCCSysDragger::showPlanarTranslationXY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::showPlanarTranslationYZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::showPlanarTranslationZX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::hidePlanarTranslationXY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoFCCSysDragger::hidePlanarTranslationYZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoFCCSysDragger::hidePlanarTranslationZX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } bool SoFCCSysDragger::isShownPlanarTranslationXY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isShownPlanarTranslationYZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isShownPlanarTranslationZX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isHiddenPlanarTranslationXY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "xyPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoFCCSysDragger::isHiddenPlanarTranslationYZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "yzPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoFCCSysDragger::isHiddenPlanarTranslationZX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "zxPlanarTranslatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } // Rotator void SoFCCSysDragger::showRotationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::showRotationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::showRotationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_ALL); } void SoFCCSysDragger::hideRotationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoFCCSysDragger::hideRotationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } void SoFCCSysDragger::hideRotationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); + SoInteractionKit::setSwitchValue(sw, SO_SWITCH_NONE); } bool SoFCCSysDragger::isShownRotationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isShownRotationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isShownRotationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_ALL); + SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_ALL); } bool SoFCCSysDragger::isHiddenRotationX() { - SoSwitch *sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "xRotatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoFCCSysDragger::isHiddenRotationY() { - SoSwitch *sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "yRotatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } bool SoFCCSysDragger::isHiddenRotationZ() { - SoSwitch *sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); - return (sw->whichChild.getValue() == SO_SWITCH_NONE); + SoSwitch* sw = SO_GET_ANY_PART(this, "zRotatorSwitch", SoSwitch); + return (sw->whichChild.getValue() == SO_SWITCH_NONE); } diff --git a/src/Mod/Arch/ArchWindow.py b/src/Mod/Arch/ArchWindow.py index 0ee9d6def2..115fddcccb 100644 --- a/src/Mod/Arch/ArchWindow.py +++ b/src/Mod/Arch/ArchWindow.py @@ -987,9 +987,9 @@ class _Window(ArchComponent.Component): if not obj.Subvolume.Shape.isNull(): sh = obj.Subvolume.Shape.copy() pl = FreeCAD.Placement(sh.Placement) - pl = pl.multiply(obj.Placement) + pl = obj.Placement.multiply(pl) if plac: - pl = pl.multiply(plac) + pl = plac.multiply(pl) sh.Placement = pl return sh diff --git a/src/Mod/Draft/WorkingPlane.py b/src/Mod/Draft/WorkingPlane.py index 985292d620..c1791d8fc8 100644 --- a/src/Mod/Draft/WorkingPlane.py +++ b/src/Mod/Draft/WorkingPlane.py @@ -1750,8 +1750,8 @@ def get_working_plane(update=True): wp = PlaneGui() if FreeCAD.GuiUp: + wp._view = view # Update _view before call to set_to_default, set_to_auto requires a 3D view. wp.set_to_default() - wp._view = view if view is not None: FreeCAD.draft_working_planes[0].append(view) FreeCAD.draft_working_planes[1].append(wp) diff --git a/src/Mod/Draft/draftfunctions/dxf.py b/src/Mod/Draft/draftfunctions/dxf.py index c5ec52ae69..1236c4fdef 100644 --- a/src/Mod/Draft/draftfunctions/dxf.py +++ b/src/Mod/Draft/draftfunctions/dxf.py @@ -77,8 +77,8 @@ def get_dxf(obj, direction=None): if direction and isinstance(direction, App.Vector): if direction != App.Vector(0, 0, 0): - plane = WorkingPlane.Plane() - plane.alignToPointAndAxis(App.Vector(0, 0, 0), direction) + plane = WorkingPlane.PlaneBase() + plane.align_to_point_and_axis(App.Vector(0, 0, 0), direction) if utils.get_type(obj) in ("Dimension", "LinearDimension"): p1 = _get_proj(obj.Start, plane=plane) diff --git a/src/Mod/Draft/draftfunctions/mirror.py b/src/Mod/Draft/draftfunctions/mirror.py index 206cd5dce2..ba62fde797 100644 --- a/src/Mod/Draft/draftfunctions/mirror.py +++ b/src/Mod/Draft/draftfunctions/mirror.py @@ -33,9 +33,10 @@ It just creates a `Part::Mirroring` object, and sets the appropriate ## \addtogroup draftfunctions # @{ import FreeCAD as App -import draftutils.utils as utils -import draftutils.gui_utils as gui_utils +import WorkingPlane +from draftutils import gui_utils +from draftutils import utils from draftutils.messages import _err from draftutils.translate import translate @@ -48,14 +49,7 @@ def mirror(objlist, p1, p2): It creates a `Part::Mirroring` object from the given `objlist` using a plane that is defined by the two given points `p1` and `p2`, - and either - - - the Draft working plane normal, or - - the negative normal provided by the camera direction - if the working plane normal does not exist and the graphical interface - is available. - - If neither of these two is available, it uses as normal the +Z vector. + and the Draft working plane normal. Parameters ---------- @@ -67,7 +61,7 @@ def mirror(objlist, p1, p2): of the resulting object. p2: Base::Vector3 - Point 1 of the mirror plane. + Point 2 of the mirror plane. Returns ------- @@ -97,13 +91,7 @@ def mirror(objlist, p1, p2): if not isinstance(objlist, list): objlist = [objlist] - if hasattr(App, "DraftWorkingPlane"): - norm = App.DraftWorkingPlane.getNormal() - elif App.GuiUp: - norm = Gui.ActiveDocument.ActiveView.getViewDirection().negative() - else: - norm = App.Vector(0, 0, 1) - + norm = WorkingPlane.get_working_plane(update=False).axis pnorm = p2.sub(p1).cross(norm).normalize() result = [] diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index 2a900f9231..cc55fef12c 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -396,7 +396,7 @@ def get_svg(obj, direction: Base::Vector3, optional It defaults to `None`. - It is an arbitrary projection vector or a `WorkingPlane.Plane` + It is an arbitrary projection vector or a `WorkingPlane.PlaneBase` instance. linestyle: optional @@ -462,13 +462,13 @@ def get_svg(obj, if direction: if isinstance(direction, App.Vector): if direction != App.Vector(0, 0, 0): - plane = WorkingPlane.plane() - plane.alignToPointAndAxis_SVG(App.Vector(0, 0, 0), - direction.negative().negative(), - 0) + plane = WorkingPlane.PlaneBase() + plane.align_to_point_and_axis_svg(App.Vector(0, 0, 0), + direction.negative().negative(), + 0) else: raise ValueError("'direction' cannot be: Vector(0, 0, 0)") - elif isinstance(direction, WorkingPlane.plane): + elif isinstance(direction, WorkingPlane.PlaneBase): plane = direction stroke = "#000000" diff --git a/src/Mod/Draft/draftfunctions/svgshapes.py b/src/Mod/Draft/draftfunctions/svgshapes.py index 33df138a70..eace6c12c1 100644 --- a/src/Mod/Draft/draftfunctions/svgshapes.py +++ b/src/Mod/Draft/draftfunctions/svgshapes.py @@ -32,6 +32,7 @@ import lazy_loader.lazy_loader as lz import FreeCAD as App import DraftVecUtils +import WorkingPlane import draftutils.utils as utils from draftutils.messages import _msg, _wrn @@ -58,8 +59,8 @@ def get_proj(vec, plane=None): vec: Base::Vector3 An arbitrary vector that will be projected on the U and V directions. - plane: WorkingPlane.Plane - An object of type `WorkingPlane`. + plane: WorkingPlane.PlaneBase + Working plane. """ if not plane: return vec @@ -124,13 +125,10 @@ def _get_path_circ_ellipse(plane, edge, verts, edata, iscircle, isellipse, fill, stroke, linewidth, lstyle): """Get the edge data from a path that is a circle or ellipse.""" - if hasattr(App, "DraftWorkingPlane"): - drawing_plane_normal = App.DraftWorkingPlane.axis - else: - drawing_plane_normal = App.Vector(0, 0, 1) - if plane: drawing_plane_normal = plane.axis + else: + drawing_plane_normal = WorkingPlane.get_working_plane(update=False).axis center = edge.Curve ax = center.Axis @@ -272,13 +270,10 @@ def get_circle(plane, cen = get_proj(edge.Curve.Center, plane) rad = edge.Curve.Radius - if hasattr(App, "DraftWorkingPlane"): - drawing_plane_normal = App.DraftWorkingPlane.axis - else: - drawing_plane_normal = App.Vector(0, 0, 1) - if plane: drawing_plane_normal = plane.axis + else: + drawing_plane_normal = WorkingPlane.get_working_plane(update=False).axis if round(edge.Curve.Axis.getAngle(drawing_plane_normal), 2) in [0, 3.14]: # Perpendicular projection: circle diff --git a/src/Mod/Draft/draftgeoutils/wires.py b/src/Mod/Draft/draftgeoutils/wires.py index 45dec6d4bc..751f29de52 100644 --- a/src/Mod/Draft/draftgeoutils/wires.py +++ b/src/Mod/Draft/draftgeoutils/wires.py @@ -35,6 +35,7 @@ import WorkingPlane from draftgeoutils.general import geomType, vec, precision from draftgeoutils.geometry import get_normal +from draftgeoutils.geometry import project_point_on_plane from draftgeoutils.edges import findMidpoint, isLine # Delay import of module until first use because it is heavy @@ -169,9 +170,7 @@ def flattenWire(wire, origin=None, normal=None): if origin is None: origin = wire.Vertexes[0].Point - plane = WorkingPlane.plane() - plane.alignToPointAndAxis(origin, normal, 0) - points = [plane.projectPoint(vert.Point) for vert in wire.Vertexes] + points = [project_point_on_plane(vert.Point, origin, normal) for vert in wire.Vertexes] if wire.isClosed(): points.append(points[0]) new_wire = Part.makePolygon(points) diff --git a/src/Mod/Draft/draftguitools/__init__.py b/src/Mod/Draft/draftguitools/__init__.py index a269186771..e5ae062e57 100644 --- a/src/Mod/Draft/draftguitools/__init__.py +++ b/src/Mod/Draft/draftguitools/__init__.py @@ -46,19 +46,16 @@ as they normally require graphical input in the task panel or a selection in the 3D view (`Gui.Selection`). Most of these GUI tools require certain components of Draft to exist -like the `gui_snapper.Snapper`, the `WorkingPlane.Plane`, -and the `DraftGui.DraftToolBar` classes. -These classes are normally installed in the global `App` or `Gui` -namespaces, so they are accessible at all times. +like the `gui_snapper.Snapper`and the `DraftGui.DraftToolBar` classes. +These classes are normally installed in the global `Gui` namespace, +so they are accessible at all times. :: import DraftGui import draftguitools.gui_snapper - import WorkingPlane Gui.draftToolBar = DraftGui.DraftToolBar() Gui.Snapper = draftguitools.gui_snapper.Snapper() - App.DraftWorkingPlane = WorkingPlane.Plane() These classes can be imported and initialized individually but it is easier to set them up just by importing `DraftTools`. diff --git a/src/Mod/Draft/draftguitools/gui_snapper.py b/src/Mod/Draft/draftguitools/gui_snapper.py index f631b4780b..a541b3aebd 100644 --- a/src/Mod/Draft/draftguitools/gui_snapper.py +++ b/src/Mod/Draft/draftguitools/gui_snapper.py @@ -189,6 +189,10 @@ class Snapper: ('special', ':/icons/Draft_Snap_Special.svg')]) + def _get_wp(self): + return App.DraftWorkingPlane + + def init_active_snaps(self): """ set self.active_snaps according to user prefs @@ -512,8 +516,7 @@ class Snapper: def toWP(self, point): """Project the given point on the working plane, if needed.""" if self.isEnabled("WorkingPlane"): - if hasattr(App, "DraftWorkingPlane"): - return App.DraftWorkingPlane.projectPoint(point) + return self._get_wp().project_point(point) return point @@ -522,14 +525,13 @@ class Snapper: view = Draft.get3DView() pt = view.getPoint(x, y) if self.mask != "z": - if hasattr(App,"DraftWorkingPlane"): - if view.getCameraType() == "Perspective": - camera = view.getCameraNode() - p = camera.getField("position").getValue() - dv = pt.sub(App.Vector(p[0], p[1], p[2])) - else: - dv = view.getViewDirection() - return App.DraftWorkingPlane.projectPoint(pt, dv) + if view.getCameraType() == "Perspective": + camera = view.getCameraNode() + p = camera.getField("position").getValue() + dv = pt.sub(App.Vector(p[0], p[1], p[2])) + else: + dv = view.getViewDirection() + return self._get_wp().project_point(pt, dv) return pt @@ -696,14 +698,8 @@ class Snapper: if self.isEnabled('Ortho') and (not self.mask): if last: vecs = [] - if hasattr(App,"DraftWorkingPlane"): - ax = [App.DraftWorkingPlane.u, - App.DraftWorkingPlane.v, - App.DraftWorkingPlane.axis] - else: - ax = [App.Vector(1, 0, 0), - App.Vector(0, 1, 0), - App.Vector(0, 0, 1)] + wp = self._get_wp() + ax = [wp.u, wp.v, wp.axis] for a in self.polarAngles: if a == 90: vecs.extend([ax[0], ax[0].negative()]) @@ -892,12 +888,9 @@ class Snapper: """ if not self.holdPoints: return None - if hasattr(App, "DraftWorkingPlane"): - u = App.DraftWorkingPlane.u - v = App.DraftWorkingPlane.v - else: - u = App.Vector(1, 0, 0) - v = App.Vector(0, 1, 0) + wp = self._get_wp() + u = wp.u + v = wp.v if len(self.holdPoints) > 1: # first try mid points if self.isEnabled("Midpoint"): @@ -1285,10 +1278,6 @@ class Snapper: must be constrained. If no basepoint is given, the current point is used as basepoint. """ - # without the Draft module fully loaded, no axes system!" - if not hasattr(App, "DraftWorkingPlane"): - return point - point = App.Vector(point) # setup trackers if needed @@ -1307,25 +1296,26 @@ class Snapper: delta = point.sub(self.basepoint) # setting constraint axis + wp = self._get_wp() if self.mask: self.affinity = self.mask if not self.affinity: - self.affinity = App.DraftWorkingPlane.getClosestAxis(delta) + self.affinity = wp.get_closest_axis(delta) if isinstance(axis, App.Vector): self.constraintAxis = axis elif axis == "x": - self.constraintAxis = App.DraftWorkingPlane.u + self.constraintAxis = wp.u elif axis == "y": - self.constraintAxis = App.DraftWorkingPlane.v + self.constraintAxis = wp.v elif axis == "z": - self.constraintAxis = App.DraftWorkingPlane.axis + self.constraintAxis = wp.axis else: if self.affinity == "x": - self.constraintAxis = App.DraftWorkingPlane.u + self.constraintAxis = wp.u elif self.affinity == "y": - self.constraintAxis = App.DraftWorkingPlane.v + self.constraintAxis = wp.v elif self.affinity == "z": - self.constraintAxis = App.DraftWorkingPlane.axis + self.constraintAxis = wp.axis elif isinstance(self.affinity, App.Vector): self.constraintAxis = self.affinity else: @@ -1411,10 +1401,9 @@ class Snapper: shift = event.wasShiftDown() self.pt = Gui.Snapper.snap(mousepos, lastpoint=last, active=ctrl, constrain=shift) - if hasattr(App, "DraftWorkingPlane"): - self.ui.displayPoint(self.pt, last, - plane=App.DraftWorkingPlane, - mask=Gui.Snapper.affinity) + self.ui.displayPoint(self.pt, last, + plane=self._get_wp(), + mask=Gui.Snapper.affinity) if movecallback: movecallback(self.pt, self.snapInfo) @@ -1422,9 +1411,10 @@ class Snapper: """Get the global coordinates from a point.""" # Same algorithm as in validatePoint in DraftGui.py. ref = App.Vector(0, 0, 0) - if global_mode is False and hasattr(App, "DraftWorkingPlane"): - point = App.DraftWorkingPlane.getGlobalRot(point) - ref = App.DraftWorkingPlane.getGlobalCoords(ref) + if global_mode is False: + wp = self._get_wp() + point = wp.get_global_coords(point, as_vector=True) + ref = wp.get_global_coords(ref) if relative_mode is True and last is not None: ref = last self.pt = point + ref diff --git a/src/Mod/Draft/draftguitools/gui_trackers.py b/src/Mod/Draft/draftguitools/gui_trackers.py index a3d1fc8903..a54ffed8ba 100644 --- a/src/Mod/Draft/draftguitools/gui_trackers.py +++ b/src/Mod/Draft/draftguitools/gui_trackers.py @@ -140,6 +140,9 @@ class Tracker: sg.removeChild(self.switch) sg.insertChild(self.switch, 0) + def _get_wp(self): + return FreeCAD.DraftWorkingPlane + class snapTracker(Tracker): """Define Snap Mark tracker, used by tools that support snapping.""" @@ -237,8 +240,9 @@ class rectangleTracker(Tracker): super().__init__(dotted, scolor, swidth, [self.coords, line], name="rectangleTracker") - self.u = FreeCAD.DraftWorkingPlane.u - self.v = FreeCAD.DraftWorkingPlane.v + wp = self._get_wp() + self.u = wp.u + self.v = wp.v def setorigin(self, point): """Set the base point of the rectangle.""" @@ -265,7 +269,7 @@ class rectangleTracker(Tracker): if v: self.v = v else: - norm = FreeCAD.DraftWorkingPlane.u.cross(FreeCAD.DraftWorkingPlane.v) + norm = self._get_wp().axis self.v = self.u.cross(norm) def p1(self, point=None): @@ -538,7 +542,7 @@ class arcTracker(Tracker): self.trans.translation.setValue([0, 0, 0]) self.sep = coin.SoSeparator() self.autoinvert = True - self.normal = FreeCAD.DraftWorkingPlane.axis + self.normal = self._get_wp().axis self.recompute() super().__init__(dotted, scolor, swidth, [self.trans, self.sep], name="arcTracker") @@ -922,11 +926,9 @@ class PlaneTracker(Tracker): def set(self, pos=None): """Set the translation to the position.""" - if pos: - Q = FreeCAD.DraftWorkingPlane.getRotation().Rotation.Q - else: - plm = FreeCAD.DraftWorkingPlane.getPlacement() - Q = plm.Rotation.Q + plm = self._get_wp().get_placement() + Q = plm.Rotation.Q + if pos is None: pos = plm.Base self.trans.translation.setValue([pos.x, pos.y, pos.z]) self.trans.rotation.setValue([Q[0], Q[1], Q[2], Q[3]]) @@ -1162,10 +1164,8 @@ class gridTracker(Tracker): self.coords3.point.setValues(apts) #self.lines3.numVertices.setValues(aidx) self.pts = pts - self.displayHumanFigure() - self.setAxesColor() - def displayHumanFigure(self): + def displayHumanFigure(self, wp): """ Display the human figure at the grid corner. The silhouette is displayed only if: - BIM Workbench is available; @@ -1178,7 +1178,7 @@ class gridTracker(Tracker): pidx = [] param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") if param.GetBool("gridShowHuman", True) and \ - FreeCAD.DraftWorkingPlane.axis.getAngle(FreeCAD.Vector(0,0,1)) < 0.001: + wp.axis.getAngle(FreeCAD.Vector(0,0,1)) < 0.001: try: import BimProject loc = FreeCAD.Vector(-bound+self.space/2,-bound+self.space/2,0) @@ -1192,11 +1192,10 @@ class gridTracker(Tracker): self.coords_human.point.setValues(pts) self.human.numVertices.setValues(pidx) - def setAxesColor(self): + def setAxesColor(self, wp): """set axes color""" cols = [0,0] - if Draft.getParam("coloredGridAxes",True) and hasattr(FreeCAD,"DraftWorkingPlane"): - wp = FreeCAD.DraftWorkingPlane + if Draft.getParam("coloredGridAxes",True): if round(wp.u.getAngle(FreeCAD.Vector(1,0,0)),2) in (0,3.14): cols[0] = 1 elif round(wp.u.getAngle(FreeCAD.Vector(0,1,0)),2) in (0,3.14): @@ -1239,23 +1238,23 @@ class gridTracker(Tracker): def set(self,tool=False): """Move and rotate the grid according to the current working plane.""" self.reset() - Q = FreeCAD.DraftWorkingPlane.getRotation().Rotation.Q - P = FreeCAD.DraftWorkingPlane.position + wp = self._get_wp() + Q = wp.get_placement().Rotation.Q + P = wp.position self.trans.rotation.setValue([Q[0], Q[1], Q[2], Q[3]]) self.trans.translation.setValue([P.x, P.y, P.z]) - self.displayHumanFigure() - self.setAxesColor() + self.displayHumanFigure(wp) + self.setAxesColor(wp) if tool: self.on() def getClosestNode(self, point): """Return the closest node from the given point.""" - # get the 2D coords. - # point = FreeCAD.DraftWorkingPlane.projectPoint(point) - pt = FreeCAD.DraftWorkingPlane.getLocalCoords(point) + wp = self._get_wp() + pt = wp.get_local_coords(point) pu = round(pt.x / self.space, 0) * self.space pv = round(pt.y / self.space, 0) * self.space - pt = FreeCAD.DraftWorkingPlane.getGlobalCoords(Vector(pu, pv, 0)) + pt = wp.get_global_coords(Vector(pu, pv, 0)) return pt @@ -1287,7 +1286,7 @@ class boxTracker(Tracker): """Update the tracker.""" import DraftGeomUtils if not normal: - normal = FreeCAD.DraftWorkingPlane.axis + normal = self._get_wp().axis if line: if isinstance(line, list): bp = line[0] @@ -1403,10 +1402,10 @@ class archDimTracker(Tracker): def setString(self, text=None): """Set the dim string to the given value or auto value.""" - plane = FreeCAD.DraftWorkingPlane + plane = self._get_wp() p1 = Vector(self.pnts.getValues()[0].getValue()) p2 = Vector(self.pnts.getValues()[-1].getValue()) - self.norm.setValue(plane.getNormal()) + self.norm.setValue(plane.axis) # set the offset sign to prevent the dim line from intersecting the curve near the cursor sign_dx = math.copysign(1, (p2.sub(p1)).x) sign_dy = math.copysign(1, (p2.sub(p1)).y) @@ -1421,7 +1420,7 @@ class archDimTracker(Tracker): self.Distance = (p2.sub(p1)).Length text = FreeCAD.Units.Quantity(self.Distance, FreeCAD.Units.Length).UserString - self.matrix.setValue(*plane.getPlacement().Matrix.transposed().A) + self.matrix.setValue(*plane.get_placement().Matrix.transposed().A) self.string.setValue(text.encode('utf8')) # change the text position to external depending on the distance and scale values volume = self.camera.getViewVolume() @@ -1444,9 +1443,9 @@ class archDimTracker(Tracker): def p1(self, point=None): """Set or get the first point of the dim.""" - plane = FreeCAD.DraftWorkingPlane + plane = self._get_wp() if point: - p1_proj = plane.projectPoint(point) + p1_proj = plane.project_point(point) p1_proj_u = (p1_proj - plane.position).dot(plane.u.normalize()) p1_proj_v = (p1_proj - plane.position).dot(plane.v.normalize()) self.pnts.set1Value(0, p1_proj_u, p1_proj_v, 0) @@ -1456,9 +1455,9 @@ class archDimTracker(Tracker): def p2(self, point=None): """Set or get the second point of the dim.""" - plane = FreeCAD.DraftWorkingPlane + plane = self._get_wp() if point: - p2_proj = plane.projectPoint(point) + p2_proj = plane.project_point(point) p2_proj_u = (p2_proj - plane.position).dot(plane.u.normalize()) p2_proj_v = (p2_proj - plane.position).dot(plane.v.normalize()) self.pnts.set1Value(1, p2_proj_u, p2_proj_v, 0) diff --git a/src/Mod/Draft/draftmake/make_clone.py b/src/Mod/Draft/draftmake/make_clone.py index d6158cd71e..4b6e338ef8 100644 --- a/src/Mod/Draft/draftmake/make_clone.py +++ b/src/Mod/Draft/draftmake/make_clone.py @@ -88,16 +88,13 @@ def make_clone(obj, delta=None, forcedraft=False): base = utils.get_clone_base(obj[0]) cl.Label = prefix + base.Label cl.CloneOf = base - if hasattr(cl,"Material") and hasattr(obj[0],"Material"): - cl.Material = obj[0].Material if utils.get_type(obj[0]) != "BuildingPart": cl.Placement = obj[0].Placement - try: - cl.Role = base.Role - cl.Description = base.Description - cl.Tag = base.Tag - except Exception: - pass + for prop in ("Description", "IfcType", "Material", "Subvolume", "Tag"): + try: + setattr(cl, prop, getattr(base, prop)) + except Exception: + pass if App.GuiUp: gui_utils.format_object(cl, base) # Workaround to trigger update of DiffuseColor: diff --git a/src/Mod/Draft/draftmake/make_dimension.py b/src/Mod/Draft/draftmake/make_dimension.py index aecd4b48c5..e6830bcc1f 100644 --- a/src/Mod/Draft/draftmake/make_dimension.py +++ b/src/Mod/Draft/draftmake/make_dimension.py @@ -36,13 +36,14 @@ This includes linear dimensions, radial dimensions, and angular dimensions. import math import FreeCAD as App -import draftutils.utils as utils -import draftutils.gui_utils as gui_utils +import WorkingPlane +from draftutils import gui_utils +from draftutils import utils from draftutils.messages import _msg, _wrn, _err from draftutils.translate import translate -from draftobjects.dimension import (LinearDimension, - AngularDimension) + +from draftobjects.dimension import LinearDimension, AngularDimension if App.GuiUp: from draftviewproviders.view_dimension \ @@ -147,10 +148,7 @@ def make_dimension(p1, p2, p3=None, p4=None): # depending on the first three parameter values new_obj.Dimline = p3 - if hasattr(App, "DraftWorkingPlane"): - normal = App.DraftWorkingPlane.axis - else: - normal = App.Vector(0, 0, 1) + normal = WorkingPlane.get_working_plane(update=False).axis if App.GuiUp: # invert the normal if we are viewing it from the back @@ -536,11 +534,8 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), the circular arc. normal: Base::Vector3, optional - It defaults to `None`, in which case the `normal` is taken - from the currently active `App.DraftWorkingPlane.axis`. - - If the working plane is not available, then the `normal` - defaults to +Z or `Vector(0, 0, 1)`. + It defaults to `None`, in which case the axis of the current working + plane is used. Returns ------- @@ -608,10 +603,7 @@ def make_angular_dimension(center=App.Vector(0, 0, 0), return None if not normal: - if hasattr(App, "DraftWorkingPlane"): - normal = App.DraftWorkingPlane.axis - else: - normal = App.Vector(0, 0, 1) + normal = WorkingPlane.get_working_plane(update=False).axis new_obj = App.ActiveDocument.addObject("App::FeaturePython", "Dimension") diff --git a/src/Mod/Draft/draftobjects/dimension.py b/src/Mod/Draft/draftobjects/dimension.py index 1b375eb2da..484fc8e226 100644 --- a/src/Mod/Draft/draftobjects/dimension.py +++ b/src/Mod/Draft/draftobjects/dimension.py @@ -106,8 +106,9 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD as App import DraftVecUtils import DraftGeomUtils -import draftutils.utils as utils +import WorkingPlane +from draftutils import utils from draftutils.messages import _wrn from draftutils.translate import translate @@ -648,10 +649,10 @@ def measure_two_obj_angles(link_sub_1, link_sub_2): start = obj1.Shape.Edges[n1].Curve.Direction end = obj2.Shape.Edges[n2].Curve.Direction - # We get the angle from the direction of the line to the U axis - # of the working plane; we should be able to also use the V axis - start_r = DraftVecUtils.angle(start, App.DraftWorkingPlane.u) - end_r = DraftVecUtils.angle(end, App.DraftWorkingPlane.u) + # We get the angle from the U axis of the working plane + wp = WorkingPlane.get_working_plane(update=False) + start_r = DraftVecUtils.angle(start, wp.u) + end_r = DraftVecUtils.angle(end, wp.u) start = math.degrees(start_r) end = math.degrees(end_r) diff --git a/src/Mod/Draft/drafttaskpanels/task_circulararray.py b/src/Mod/Draft/drafttaskpanels/task_circulararray.py index 0a58701875..f3f7f17e8b 100644 --- a/src/Mod/Draft/drafttaskpanels/task_circulararray.py +++ b/src/Mod/Draft/drafttaskpanels/task_circulararray.py @@ -392,10 +392,8 @@ class TaskPanelCircularArray: point: Base::Vector3 is a vector that arrives by the callback. - plane: WorkingPlane - is a `WorkingPlane` instance, for example, - `App.DraftWorkingPlane`. It is not used at the moment, - but could be used to set up the grid. + plane: WorkingPlane.PlaneGui + is a working plane instance. Not used at the moment. mask: str is a string that specifies which coordinate is being edited. It is used to restrict edition of a single coordinate. diff --git a/src/Mod/Draft/drafttaskpanels/task_polararray.py b/src/Mod/Draft/drafttaskpanels/task_polararray.py index 81e3f8227e..f4888bd0e1 100644 --- a/src/Mod/Draft/drafttaskpanels/task_polararray.py +++ b/src/Mod/Draft/drafttaskpanels/task_polararray.py @@ -346,9 +346,7 @@ class TaskPanelPolarArray: point : is a vector that arrives by the callback. plane : - is a `WorkingPlane` instance, for example, - `App.DraftWorkingPlane`. It is not used at the moment, - but could be used to set up the grid. + is a `WorkingPlane.PlaneGui` instance. Not used at the moment. mask : is a string that specifies which coordinate is being edited. It is used to restrict edition of a single coordinate. diff --git a/src/Mod/Draft/draftviewproviders/view_wire.py b/src/Mod/Draft/draftviewproviders/view_wire.py index 1b33202180..c8297c871e 100644 --- a/src/Mod/Draft/draftviewproviders/view_wire.py +++ b/src/Mod/Draft/draftviewproviders/view_wire.py @@ -39,6 +39,7 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD as App import FreeCADGui as Gui import DraftVecUtils +import WorkingPlane import draftgeoutils.wires as wires import draftutils.utils as utils import draftutils.gui_utils as gui_utils @@ -152,20 +153,10 @@ class ViewProviderWire(ViewProviderDraft): if not hasattr(self, "Object"): return - if hasattr(App, "DraftWorkingPlane"): - App.DraftWorkingPlane.setup() - origin = App.DraftWorkingPlane.position - normal = App.DraftWorkingPlane.axis - # Align the grid for visual feedback: - if hasattr(Gui, "Snapper"): - Gui.Snapper.setTrackers() - else: - origin = App.Vector(0, 0, 0) - normal = App.Vector(0, 0, 1) - + wp = WorkingPlane.get_working_plane() flat_wire = wires.flattenWire(self.Object.Shape.Wires[0], - origin=origin, - normal=normal) + origin=wp.position, + normal=wp.axis) doc = App.ActiveDocument doc.openTransaction(translate("draft", "Flatten")) diff --git a/src/Mod/Draft/importDXF.py b/src/Mod/Draft/importDXF.py index 4ffd1a2622..c146e9a8ca 100644 --- a/src/Mod/Draft/importDXF.py +++ b/src/Mod/Draft/importDXF.py @@ -65,11 +65,6 @@ from Draft import _Dimension from FreeCAD import Vector from FreeCAD import Console as FCC -# sets the default working plane if Draft hasn't been started yet -if not hasattr(FreeCAD, "DraftWorkingPlane"): - plane = WorkingPlane.plane() - FreeCAD.DraftWorkingPlane = plane - gui = FreeCAD.GuiUp draftui = None if gui: @@ -739,10 +734,10 @@ def placementFromDXFOCS(ent): what is needed is a 3D vector defining the Z axis of the OCS, and the elevation value over it. - It uses `WorkingPlane.alignToPointAndAxis()` to align the working plane + It uses `WorkingPlane.align_to_point_and_axis()` to align the working plane to the origin and to `ent.extrusion` (the plane's `axis`). Then it gets the global coordinates of the entity - by using `WorkingPlane.getGlobalCoords()` + by using `WorkingPlane.get_global_coords()` and either `ent.elevation` (Z coordinate) or `ent.loc` a `(x,y,z)` tuple. Parameters @@ -760,11 +755,11 @@ def placementFromDXFOCS(ent): See also -------- - WorkingPlane.alignToPointAndAxis, WorkingPlane.getGlobalCoords + WorkingPlane.align_to_point_and_axis, WorkingPlane.get_global_coords """ - draftWPlane = FreeCAD.DraftWorkingPlane - draftWPlane.alignToPointAndAxis(Vector(0.0, 0.0, 0.0), - vec(ent.extrusion), 0.0) + draftWPlane = WorkingPlane.PlaneBase() + draftWPlane.align_to_point_and_axis(Vector(0.0, 0.0, 0.0), + vec(ent.extrusion), 0.0) # Object Coordinate Systems (OCS) # http://docs.autodesk.com/ACD/2011/ENU/filesDXF/WS1a9193826455f5ff18cb41610ec0a2e719-7941.htm # Arbitrary Axis Algorithm @@ -787,14 +782,12 @@ def placementFromDXFOCS(ent): draftWPlane.v = draftWPlane.axis.cross(draftWPlane.u) draftWPlane.v.normalize() draftWPlane.position = Vector(0.0, 0.0, 0.0) - draftWPlane.weak = False - pl = FreeCAD.Placement() - pl = draftWPlane.getPlacement() + pl = draftWPlane.get_placement() if ((ent.type == "lwpolyline") or (ent.type == "polyline")): - pl.Base = draftWPlane.getGlobalCoords(vec([0.0, 0.0, ent.elevation])) + pl.Base = draftWPlane.get_global_coords(vec([0.0, 0.0, ent.elevation])) else: - pl.Base = draftWPlane.getGlobalCoords(vec(ent.loc)) + pl.Base = draftWPlane.get_global_coords(vec(ent.loc)) return pl @@ -2305,7 +2298,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): edges.extend(s.Edges) if len(edges) > (100): FCC.PrintMessage(str(len(edges)) + " edges to join\n") - if FreeCAD.GuiUp: + if gui: d = QtGui.QMessageBox() d.setText("Warning: High number of entities to join (>100)") d.setInformativeText("This might take a long time " @@ -2528,7 +2521,7 @@ def processdxf(document, filename, getShapes=False, reComputeFlag=True): newob = doc.addObject("App::FeaturePython", "Dimension") lay.addObject(newob) _Dimension(newob) - if FreeCAD.GuiUp: + if gui: from Draft import _ViewProviderDimension _ViewProviderDimension(newob.ViewObject) newob.Start = p1 @@ -3526,8 +3519,7 @@ def export(objectslist, filename, nospline=False, lwPoly=False): getDXFlibs() if dxfLibrary: global exportList - exportList = objectslist - exportList = Draft.get_group_contents(exportList) + exportList = Draft.get_group_contents(objectslist, spaces=True) nlist = [] exportLayers = [] @@ -3609,36 +3601,30 @@ def export(objectslist, filename, nospline=False, lwPoly=False): elif obtype == "PanelCut": writePanelCut(ob, dxf, nospline, lwPoly) - elif obtype == "Space": + elif obtype == "Space" and gui: vobj = ob.ViewObject - c = utils.get_rgb(vobj.TextColor) - n = vobj.FontName - a = 0 - if rotation != 0: - a = math.radians(rotation) + rotation = math.degrees(ob.Placement.Rotation.Angle) t1 = "".join(vobj.Proxy.text1.string.getValues()) t2 = "".join(vobj.Proxy.text2.string.getValues()) - scale = vobj.FirstLine.Value/vobj.FontSize.Value - f1 = fontsize * scale - if round(FreeCAD.DraftWorkingPlane.axis.getAngle(App.Vector(0,0,1)),2) not in [0,3.14]: - # if not in XY view, place the label at center - p2 = obj.Shape.CenterOfMass - else: - _v = vobj.Proxy.coords.translation.getValue().getValue() - p2 = obj.Placement.multVec(App.Vector(_v)) + h1 = vobj.FirstLine.Value + h2 = vobj.FontSize.Value + _v = vobj.Proxy.coords.translation.getValue().getValue() _h = vobj.Proxy.header.translation.getValue().getValue() + p2 = FreeCAD.Vector(_v) lspc = FreeCAD.Vector(_h) - p1 = p2 + lspc - dxf.append(dxfLibrary.Text(t1, p1, height=f1, + p1 = ob.Placement.multVec(p2 + lspc) + dxf.append(dxfLibrary.Text(t1, p1, height=h1 * 0.8, + rotation=rotation, color=getACI(ob, text=True), style='STANDARD', layer=getStrGroup(ob))) if t2: ofs = FreeCAD.Vector(0, -lspc.Length, 0) - if a: + if rotation: Z = FreeCAD.Vector(0, 0, 1) - ofs = FreeCAD.Rotation(Z, -rotation).multVec(ofs) - dxf.append(dxfLibrary.Text(t2, p1.add(ofs), height=f1, + ofs = FreeCAD.Rotation(Z, rotation).multVec(ofs) + dxf.append(dxfLibrary.Text(t2, p1.add(ofs), height=h2 * 0.8, + rotation=rotation, color=getACI(ob, text=True), style='STANDARD', layer=getStrGroup(ob))) @@ -3653,7 +3639,7 @@ def export(objectslist, filename, nospline=False, lwPoly=False): color=getACI(ob), layer=getStrGroup(ob))) h = 1 - if FreeCAD.GuiUp: + if gui: vobj = ob.ViewObject h = float(ob.ViewObject.FontSize) for text in vobj.Proxy.getTextData(): @@ -4059,7 +4045,7 @@ def readPreferences(): """ # reading parameters p = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") - if FreeCAD.GuiUp and p.GetBool("dxfShowDialog", False): + if gui and p.GetBool("dxfShowDialog", False): FreeCADGui.showPreferences("Import-Export", 3) global dxfCreatePart, dxfCreateDraft, dxfCreateSketch global dxfDiscretizeCurves, dxfStarBlocks diff --git a/src/Mod/Draft/importSVG.py b/src/Mod/Draft/importSVG.py index 588be1bf9c..2c5c12e477 100644 --- a/src/Mod/Draft/importSVG.py +++ b/src/Mod/Draft/importSVG.py @@ -1896,7 +1896,7 @@ def export(exportList, filename): # raw-style exports do not translate the sketch svg.write('\n' % ob.Name) - svg.write(Draft.get_svg(ob)) + svg.write(Draft.get_svg(ob, override=False)) _label_enc = str(ob.Label.encode('utf8')) _label = _label_enc.replace('<', '<').replace('>', '>') # replace('"', """) diff --git a/src/Mod/Part/App/AppPartPy.cpp b/src/Mod/Part/App/AppPartPy.cpp index 1ab082d699..6e219af4e9 100644 --- a/src/Mod/Part/App/AppPartPy.cpp +++ b/src/Mod/Part/App/AppPartPy.cpp @@ -607,7 +607,7 @@ public: "* transform: if False, then skip obj's transformation. Use this if mat already include obj's\n" " transformation matrix\n" "* retType: 0: return TopoShape,\n" - " 1: return (shape,subObj,mat), where subObj is the object referenced in 'subname',\n" + " 1: return (shape,mat,subObj), where subObj is the object referenced in 'subname',\n" " and 'mat' is the accumulated transformation matrix of that sub-object.\n" " 2: same as 1, but make sure 'subObj' is resolved if it is a link.\n" "* refine: refine the returned shape" diff --git a/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml b/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml index 4e0e12b7d3..941d20c07a 100644 --- a/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml +++ b/src/Mod/Part/App/GeomPlate/CurveConstraintPy.xml @@ -77,32 +77,41 @@ Raises an exception if the curve is not on a surface - + Allows you to set the G2 criterion. This is the law + defining the greatest difference in curvature allowed + between the constraint and the target surface. If this + criterion is not set, TolCurv, the curvature tolerance from + the constructor, is used. + Raises ConstructionError if the point is not on the surface + - + Returns a 3d curve associated the surface resulting of the constraints - + loads a 2d curve associated the surface resulting of the constraints + - + Returns a 2d curve associated the surface resulting of the constraints - + loads a 2d curve resulting from the normal projection of + the curve on the initial surface - + Returns the projected curve resulting from the normal projection of the + curve on the initial surface @@ -116,19 +125,22 @@ the number of points. - + This function returns the first parameter of the curve. +The first parameter is the lowest parametric value for the curve, which defines the starting point of the curve. - + This function returns the last parameter of the curve. +The last parameter is the highest parametric value for the curve, which defines the ending point of the curve. - + This function returns the length of the curve. +The length of the curve is a geometric property that indicates how long the curve is in the space. diff --git a/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml b/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml index bc357852b4..60c9699e3f 100644 --- a/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml +++ b/src/Mod/Part/App/GeomPlate/PointConstraintPy.xml @@ -77,22 +77,26 @@ Raises an exception if the curve is not on a surface - + Allows you to set the G2 criterion. This is the law + defining the greatest difference in curvature allowed between the + constraint and the target surface. If this criterion is not + set, TolCurv, the curvature tolerance from the constructor, is used. + Raises ConstructionError if the curve is not on a surface - + Checks if there is a 2D point associated with the surface. It returns a boolean indicating whether such a point exists. - + Allows you to set a 2D point on the surface. It takes a gp_Pnt2d as an argument, representing the 2D point to be associated with the surface. - + Returns the 2D point on the surface. It returns a gp_Pnt2d representing the associated 2D point. diff --git a/src/Mod/Part/Gui/SectionCutting.cpp b/src/Mod/Part/Gui/SectionCutting.cpp index ddf2c15b7d..7e032f03cf 100644 --- a/src/Mod/Part/Gui/SectionCutting.cpp +++ b/src/Mod/Part/Gui/SectionCutting.cpp @@ -26,7 +26,7 @@ // to avoid compiler warnings of redefining contents of basic.h // later by #include -# define _USE_MATH_DEFINES +# define _USE_MATH_DEFINES // NOLINT # include # include @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -66,146 +67,148 @@ using namespace PartGui; -enum Refresh : bool +namespace { - notXValue = false, - notYValue = false, - notZValue = false, - notXRange = false, - notYRange = false, - notZRange = false, - XValue = true, - YValue = true, - ZValue = true, - XRange = true, - YRange = true, - ZRange = true +struct Refresh +{ + static const bool notXValue = false; + static const bool notYValue = false; + static const bool notZValue = false; + static const bool notXRange = false; + static const bool notYRange = false; + static const bool notZRange = false; + //static const bool XValue = true; + static const bool YValue = true; + static const bool ZValue = true; + static const bool XRange = true; + static const bool YRange = true; + static const bool ZRange = true; }; +} +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) SectionCut::SectionCut(QWidget* parent) : QDialog(parent) , ui(new Ui_SectionCut) { // create widgets ui->setupUi(this); - ui->cutX->setRange(-INT_MAX, INT_MAX); - ui->cutY->setRange(-INT_MAX, INT_MAX); - ui->cutZ->setRange(-INT_MAX, INT_MAX); + initSpinBoxes(); // get all objects in the document auto docGui = Gui::Application::Instance->activeDocument(); if (!docGui) { - Base::Console().Error("SectionCut error: there is no document\n"); - return; + throw Base::RuntimeError("SectionCut error: there is no document"); } doc = docGui->getDocument(); if (!doc) { - Base::Console().Error("SectionCut error: there is no document\n"); - return; + throw Base::RuntimeError("SectionCut error: there is no document"); } std::vector ObjectsList = doc->getObjects(); if (ObjectsList.empty()) { - Base::Console().Error("SectionCut error: there are no objects in the document\n"); - return; - } - // now store those that are currently visible - for (auto anObject : ObjectsList) { - if (anObject->Visibility.getValue()) - ObjectsListVisible.emplace_back(anObject); + throw Base::RuntimeError("SectionCut error: there are no objects in the document"); } + // now store those that are currently visible + for (auto anObject : ObjectsList) { + if (anObject->Visibility.getValue()) { + ObjectsListVisible.emplace_back(anObject); + } + } + + // if we can have existing cut boxes, take their values + // to access the flip state we must compare the bounding boxes of the cutbox and the compound + Base::BoundBox3d BoundCompound = collectObjects(); + initControls(BoundCompound); + + // hide existing cuts to check if there are objects to be cut visible + hideCutObjects(); + + initCutRanges(); + + setupConnections(); + + tryStartCutting(); +} + +void SectionCut::initSpinBoxes() +{ + ui->cutX->setRange(-INT_MAX, INT_MAX); + ui->cutY->setRange(-INT_MAX, INT_MAX); + ui->cutZ->setRange(-INT_MAX, INT_MAX); +} + +void SectionCut::initControls(const Base::BoundBox3d& BoundCompound) +{ // lambda function to set color and transparency auto setColorTransparency = [&](Part::Box* pcBox) { App::Color cutColor; - long cutTransparency; + long cutTransparency{}; auto vpBox = dynamic_cast( Gui::Application::Instance->getViewProvider(pcBox)); if (vpBox) { cutColor = vpBox->ShapeColor.getValue(); cutTransparency = vpBox->Transparency.getValue(); ui->CutColor->setColor(cutColor.asValue()); - ui->CutTransparencyHS->setValue(cutTransparency); + ui->CutTransparencyHS->setValue(int(cutTransparency)); ui->CutTransparencyHS->setToolTip(QString::number(cutTransparency) + QString::fromLatin1(" %")); } }; - // if we can have existing cut boxes, take their values - // to access the flip state we must compare the bounding boxes of the cutbox and the compound - Base::BoundBox3d BoundCompound; - Base::BoundBox3d BoundCutBox; - if (doc->getObject(BoxXName) || doc->getObject(BoxYName) || doc->getObject(BoxZName)) { - // automatic coloring must be disabled - ui->autoCutfaceColorCB->setChecked(false); - ui->autoBFColorCB->setChecked(false); - if (doc->getObject(CompoundName)) { - // get the object with the right name - auto compoundObject = doc->getObject(CompoundName); - // to later store the childs - std::vector compoundChilds; + initZControls(BoundCompound, setColorTransparency); + initYControls(BoundCompound, setColorTransparency); + initXControls(BoundCompound, setColorTransparency); +} - // check if this is a BooleanFragments or a Part::Compound - // Part::Compound is the case when there was only one object - Part::Compound* pcCompoundPart = dynamic_cast(compoundObject); - if (!pcCompoundPart) { - // for more security check for validity accessing its ViewProvider - auto pcCompoundBF = Gui::Application::Instance->getViewProvider(compoundObject); - if (!pcCompoundBF) { - Base::Console().Error( - "SectionCut error: compound is incorrectly named, cannot proceed\n"); - return; - } - auto property = compoundObject->getPropertyByName("Shape"); - Part::PropertyPartShape* objectShape = - static_cast(property); - BoundCompound = objectShape->getBoundingBox(); - // for BooleanFragments we also need to set the checkbox, transparency and color - ui->groupBoxIntersecting->setChecked(true); - auto pcCompoundBFGO = dynamic_cast(pcCompoundBF); - if (pcCompoundBFGO) { - App::Color compoundColor = pcCompoundBFGO->ShapeColor.getValue(); - ui->BFragColor->setColor(compoundColor.asValue()); - int compoundTransparency = pcCompoundBFGO->Transparency.getValue(); - ui->BFragTransparencyHS->setValue(compoundTransparency); - ui->BFragTransparencyHS->setToolTip(QString::number(compoundTransparency) - + QString::fromLatin1(" %")); - // Part::Cut ignores the cutbox transparency when it is set - // to zero and the BooleanFragments transparency is not zero - // therefore limit the cutbox transparency to 1 in this case - if (compoundTransparency > 0) - ui->CutTransparencyHS->setMinimum(1); - else - ui->CutTransparencyHS->setMinimum(0); - } - compoundChilds = pcCompoundBF->claimChildren(); - } - else { - BoundCompound = pcCompoundPart->Shape.getBoundingBox(); - pcCompoundPart->Links.getLinks(compoundChilds); - } - // make parent objects of links visible to handle the case that - // the cutting is started when only an existing cut was visible - for (auto aCompoundObj : compoundChilds) { - App::Link* pcLink = dynamic_cast(aCompoundObj); - auto LinkedObject = pcLink ? pcLink->getLink() : nullptr; - if (LinkedObject) { - // only if not already visible - if (!(LinkedObject->Visibility.getValue())) { - LinkedObject->Visibility.setValue(true); - ObjectsListVisible.emplace_back(LinkedObject); - } - } - } +void SectionCut::initXControls(const Base::BoundBox3d& BoundCompound, + const std::function& setTransparency) +{ + Base::BoundBox3d BoundCutBox; + if (auto pcBox = findCutBox(BoxXName)) { + hasBoxX = true; + ui->groupBoxX->setChecked(true); + BoundCutBox = pcBox->Shape.getBoundingBox(); + if (BoundCutBox.MinX > BoundCompound.MinX) { + ui->cutX->setValue(pcBox->Placement.getValue().getPosition().x); + ui->flipX->setChecked(true); } + else { + ui->cutX->setValue(pcBox->Length.getValue() + + pcBox->Placement.getValue().getPosition().x); + ui->flipX->setChecked(false); + } + setTransparency(pcBox); } - if (doc->getObject(BoxZName)) { - Part::Box* pcBox = dynamic_cast(doc->getObject(BoxZName)); - if (!pcBox) { - Base::Console().Error( - "SectionCut error: cut box is incorrectly named, cannot proceed\n"); - return; +} + +void SectionCut::initYControls(const Base::BoundBox3d& BoundCompound, + const std::function& setTransparency) +{ + Base::BoundBox3d BoundCutBox; + if (auto pcBox = findCutBox(BoxYName)) { + hasBoxY = true; + ui->groupBoxY->setChecked(true); + BoundCutBox = pcBox->Shape.getBoundingBox(); + if (BoundCutBox.MinY > BoundCompound.MinY) { + ui->cutY->setValue(pcBox->Placement.getValue().getPosition().y); + ui->flipY->setChecked(true); } + else { + ui->cutY->setValue(pcBox->Width.getValue() + + pcBox->Placement.getValue().getPosition().y); + ui->flipY->setChecked(false); + } + setTransparency(pcBox); + } +} + +void SectionCut::initZControls(const Base::BoundBox3d& BoundCompound, + const std::function& setTransparency) +{ + Base::BoundBox3d BoundCutBox; + if (auto pcBox = findCutBox(BoxZName)) { hasBoxZ = true; ui->groupBoxZ->setChecked(true); // if z of cutbox bounding is greater than z of compound bounding @@ -221,73 +224,103 @@ SectionCut::SectionCut(QWidget* parent) ui->flipZ->setChecked(false); } // set color and transparency - setColorTransparency(pcBox); - } - if (doc->getObject(BoxYName)) { - Part::Box* pcBox = dynamic_cast(doc->getObject(BoxYName)); - if (!pcBox) { - Base::Console().Error( - "SectionCut error: cut box is incorrectly named, cannot proceed\n"); - return; - } - hasBoxY = true; - ui->groupBoxY->setChecked(true); - BoundCutBox = pcBox->Shape.getBoundingBox(); - if (BoundCutBox.MinY > BoundCompound.MinY) { - ui->cutY->setValue(pcBox->Placement.getValue().getPosition().y); - ui->flipY->setChecked(true); - } - else { - ui->cutY->setValue(pcBox->Width.getValue() - + pcBox->Placement.getValue().getPosition().y); - ui->flipY->setChecked(false); - } - setColorTransparency(pcBox); - } - if (doc->getObject(BoxXName)) { - Part::Box* pcBox = dynamic_cast(doc->getObject(BoxXName)); - if (!pcBox) { - Base::Console().Error( - "SectionCut error: cut box is incorrectly named, cannot proceed\n"); - return; - } - hasBoxX = true; - ui->groupBoxX->setChecked(true); - BoundCutBox = pcBox->Shape.getBoundingBox(); - if (BoundCutBox.MinX > BoundCompound.MinX) { - ui->cutX->setValue(pcBox->Placement.getValue().getPosition().x); - ui->flipX->setChecked(true); - } - else { - ui->cutX->setValue(pcBox->Length.getValue() - + pcBox->Placement.getValue().getPosition().x); - ui->flipX->setChecked(false); - } - setColorTransparency(pcBox); + setTransparency(pcBox); } +} - // hide existing cuts to check if there are objects to be cut visible - if (doc->getObject(CutXName)) - doc->getObject(CutXName)->Visibility.setValue(false); - if (doc->getObject(CutYName)) - doc->getObject(CutYName)->Visibility.setValue(false); - if (doc->getObject(CutZName)) - doc->getObject(CutZName)->Visibility.setValue(false); - +void SectionCut::initCutRanges() +{ // get bounding box SbBox3f box = getViewBoundingBox(); - if (!box.isEmpty()) { + if (!box.isEmpty()) { // NOLINT // if there is a cut box, perform the cut if (hasBoxX || hasBoxY || hasBoxZ) { // refresh only the range since we set the values above already refreshCutRanges(box, Refresh::notXValue, Refresh::notYValue, Refresh::notZValue, Refresh::XRange, Refresh::YRange, Refresh::ZRange); } - else + else { refreshCutRanges(box); + } } - // the case of an empty box and having cuts will be handles later by startCutting(true) +} +void SectionCut::tryStartCutting() +{ + // if there is a cut, perform it + if (hasBoxX || hasBoxY || hasBoxZ) { + ui->RefreshCutPB->setEnabled(false); + startCutting(true); + } +} + +Base::BoundBox3d SectionCut::collectObjects() +{ + Base::BoundBox3d BoundCompound; + if (doc->getObject(BoxXName) || doc->getObject(BoxYName) || doc->getObject(BoxZName)) { + // automatic coloring must be disabled + ui->autoCutfaceColorCB->setChecked(false); + ui->autoBFColorCB->setChecked(false); + if (doc->getObject(CompoundName)) { + // get the object with the right name + auto compoundObject = doc->getObject(CompoundName); + // to later store the childs + std::vector compoundChilds; + + // check if this is a BooleanFragments or a Part::Compound + // Part::Compound is the case when there was only one object + auto pcCompoundPart = dynamic_cast(compoundObject); + auto pcPartFeature = dynamic_cast(compoundObject); + if (!pcCompoundPart && pcPartFeature) { + // for more security check for validity accessing its ViewProvider + auto pcCompoundBF = Gui::Application::Instance->getViewProvider(pcPartFeature); + if (!pcCompoundBF) { + throw Base::RuntimeError("SectionCut error: compound is incorrectly named, cannot proceed"); + } + + BoundCompound = pcPartFeature->Shape.getBoundingBox(); + // for BooleanFragments we also need to set the checkbox, transparency and color + ui->groupBoxIntersecting->setChecked(true); + auto pcCompoundBFGO = dynamic_cast(pcCompoundBF); + if (pcCompoundBFGO) { + App::Color compoundColor = pcCompoundBFGO->ShapeColor.getValue(); + ui->BFragColor->setColor(compoundColor.asValue()); + long compoundTransparency = pcCompoundBFGO->Transparency.getValue(); + ui->BFragTransparencyHS->setValue(int(compoundTransparency)); + ui->BFragTransparencyHS->setToolTip(QString::number(compoundTransparency) + + QString::fromLatin1(" %")); + // Part::Cut ignores the cutbox transparency when it is set + // to zero and the BooleanFragments transparency is not zero + // therefore limit the cutbox transparency to 1 in this case + ui->CutTransparencyHS->setMinimum(compoundTransparency > 0 ? 1 : 0); + } + compoundChilds = pcCompoundBF->claimChildren(); + } + else if (pcCompoundPart) { + BoundCompound = pcCompoundPart->Shape.getBoundingBox(); + pcCompoundPart->Links.getLinks(compoundChilds); + } + // make parent objects of links visible to handle the case that + // the cutting is started when only an existing cut was visible + for (auto aCompoundObj : compoundChilds) { + auto pcLink = dynamic_cast(aCompoundObj); + auto LinkedObject = pcLink ? pcLink->getLink() : nullptr; + if (LinkedObject) { + // only if not already visible + if (!(LinkedObject->Visibility.getValue())) { + LinkedObject->Visibility.setValue(true); + ObjectsListVisible.emplace_back(LinkedObject); + } + } + } + } + } + + return BoundCompound; +} + +void SectionCut::setupConnections() +{ connect(ui->groupBoxX, &QGroupBox::toggled, this, &SectionCut::onGroupBoxXtoggled); connect(ui->groupBoxY, &QGroupBox::toggled, this, &SectionCut::onGroupBoxYtoggled); connect(ui->groupBoxZ, &QGroupBox::toggled, this, &SectionCut::onGroupBoxZtoggled); @@ -319,11 +352,18 @@ SectionCut::SectionCut(QWidget* parent) this, &SectionCut::onBFragTransparencyHSMoved); connect(ui->BFragTransparencyHS,&QSlider::valueChanged, this, &SectionCut::onBFragTransparencyHSChanged); +} - // if there is a cut, perform it - if (hasBoxX || hasBoxY || hasBoxZ) { - ui->RefreshCutPB->setEnabled(false); - startCutting(true); +void SectionCut::hideCutObjects() +{ + if (auto obj = doc->getObject(CutXName)) { + obj->Visibility.setValue(false); + } + if (auto obj = doc->getObject(CutYName)) { + obj->Visibility.setValue(false); + } + if (auto obj = doc->getObject(CutZName)) { + obj->Visibility.setValue(false); } } @@ -352,9 +392,10 @@ void SectionCut::startCutting(bool isInitial) return; } // the document might have been changed - if (doc != Gui::Application::Instance->activeDocument()->getDocument()) + if (doc != Gui::Application::Instance->activeDocument()->getDocument()) { // refresh documents list onRefreshCutPBclicked(); + } App::DocumentObject* anObject = nullptr; @@ -366,8 +407,9 @@ void SectionCut::startCutting(bool isInitial) ObjectsListVisible.begin(), ObjectsListVisible.end(), [anObject](const App::DocumentObjectT &obj) { return (obj.getObject() == anObject); }); - if (found != ObjectsListVisible.end()) + if (found != ObjectsListVisible.end()) { ObjectsListVisible.erase(found); + } doc->removeObject(objectName); }; @@ -377,7 +419,7 @@ void SectionCut::startCutting(bool isInitial) auto CompoundVP = dynamic_cast( Gui::Application::Instance->getViewProvider(cutObject)); if (CompoundVP && compoundTransparency == -1) { - compoundTransparency = CompoundVP->Transparency.getValue(); + compoundTransparency = int(CompoundVP->Transparency.getValue()); } }; @@ -391,20 +433,23 @@ void SectionCut::startCutting(bool isInitial) storeTransparency(doc->getObject(CutZName)); deleteObject(CutZName); } - if (doc->getObject(BoxZName)) + if (doc->getObject(BoxZName)) { deleteObject(BoxZName); + } if (doc->getObject(CutYName)) { storeTransparency(doc->getObject(CutYName)); deleteObject(CutYName); } - if (doc->getObject(BoxYName)) + if (doc->getObject(BoxYName)) { deleteObject(BoxYName); + } if (doc->getObject(CutXName)) { storeTransparency(doc->getObject(CutXName)); deleteObject(CutXName); } - if (doc->getObject(BoxXName)) + if (doc->getObject(BoxXName)) { deleteObject(BoxXName); + } if (doc->getObject(CompoundName)) { // get the object with the right name auto compoundObject = doc->getObject(CompoundName); @@ -412,8 +457,8 @@ void SectionCut::startCutting(bool isInitial) std::vector compoundChilds; // check if this is a BooleanFragments or a Part::Compound - Part::Compound* pcCompoundDelPart = dynamic_cast(compoundObject); - Gui::ViewProvider* pcCompoundDelBF; + auto pcCompoundDelPart = dynamic_cast(compoundObject); + Gui::ViewProvider* pcCompoundDelBF{}; if (!pcCompoundDelPart) { // check for BooleanFragments pcCompoundDelBF = Gui::Application::Instance->getViewProvider(compoundObject); @@ -433,8 +478,9 @@ void SectionCut::startCutting(bool isInitial) ObjectsListVisible.begin(), ObjectsListVisible.end(), [anObject](const App::DocumentObjectT &obj) { return (obj.getObject() == anObject); }); - if (foundObj != ObjectsListVisible.end()) + if (foundObj != ObjectsListVisible.end()) { ObjectsListVisible.erase(foundObj); + } doc->removeObject(CompoundName); // now delete the objects that have been part of the compound for (auto aChild : compoundChilds) { @@ -443,8 +489,9 @@ void SectionCut::startCutting(bool isInitial) [anObject](const App::DocumentObjectT &objInner) { return (objInner.getObject() == anObject); }); - if (foundObjInner != ObjectsListVisible.end()) + if (foundObjInner != ObjectsListVisible.end()) { ObjectsListVisible.erase((foundObjInner)); + } doc->removeObject(aChild->getNameInDocument()); } } @@ -452,8 +499,10 @@ void SectionCut::startCutting(bool isInitial) // make all objects visible that have been visible when the dialog was called // because we made them invisible when we created cuts for (auto& aVisObject : ObjectsListVisible) { - if (aVisObject.getObject()) // a formerly visible object might have been deleted + if (aVisObject.getObject()) { + // a formerly visible object might have been deleted aVisObject.getObject()->Visibility.setValue(true); + } else { // we must refresh the ObjectsListVisible list onRefreshCutPBclicked(); @@ -475,9 +524,7 @@ void SectionCut::startCutting(bool isInitial) continue; } // we need all Link objects in App::Part for example for Assembly 4 - if (object->getTypeId() == Base::Type::fromName("App::Part")) { - App::Part* pcPart = static_cast(object); - + if (auto pcPart = dynamic_cast(object)) { // collect all its link objects auto groupObjects = pcPart->Group.getValue(); for (auto aGroupObject : groupObjects) { @@ -489,7 +536,7 @@ void SectionCut::startCutting(bool isInitial) } } // get all shapes that are also Part::Features - if (object->getPropertyByName("Shape") + if (object->getPropertyByName("Shape") != nullptr && object->getTypeId().isDerivedFrom( Base::Type::fromName("Part::Feature"))) { // sort out 2D objects, datums, App:Parts, compounds and objects that are @@ -502,16 +549,17 @@ void SectionCut::startCutting(bool isInitial) Base::Type::fromName("PartDesign::Feature")) && !object->getTypeId().isDerivedFrom( Base::Type::fromName("Part::Compound")) - && object->getTypeId() != Base::Type::fromName("App::Part")) + && object->getTypeId() != Base::Type::fromName("App::Part")) { ObjectsListCut.push_back(object); + } } // get Links that are derived from Part objects - if (object->getTypeId() == Base::Type::fromName("App::Link")) { - App::Link* pcLink = static_cast(object); + if (auto pcLink = dynamic_cast(object)) { auto linkedObject = doc->getObject(pcLink->LinkedObject.getObjectName()); - if (linkedObject - && linkedObject->getTypeId().isDerivedFrom(Base::Type::fromName("Part::Feature"))) + if (linkedObject != nullptr + && linkedObject->getTypeId().isDerivedFrom(Base::Type::fromName("Part::Feature"))) { ObjectsListCut.push_back(object); + } } } @@ -562,11 +610,13 @@ void SectionCut::startCutting(bool isInitial) // we might have no objects that can be cut if (ObjectsListCut.empty()) { - if (isInitial) + if (isInitial) { Base::Console().Error("SectionCut error: there are no visible objects to be cut\n"); - else + } + else { Base::Console().Error( "SectionCut error: there are no objects in the document that can be cut\n"); + } // block signals to be able to reset the cut group boxes without calling startCutting again ui->groupBoxX->blockSignals(true); ui->groupBoxY->blockSignals(true); @@ -610,7 +660,7 @@ void SectionCut::startCutting(bool isInitial) Gui::Application::Instance->getViewProvider(*ObjectsListCut.begin())); if (vpFirstObject) { cutColor = vpFirstObject->ShapeColor.getValue(); - cutTransparency = vpFirstObject->Transparency.getValue(); + cutTransparency = int(vpFirstObject->Transparency.getValue()); } // create link objects for all found elements std::vector ObjectsListLinks; @@ -619,37 +669,39 @@ void SectionCut::startCutting(bool isInitial) std::string newName; // since links to normal Part objects all have the document name "Link", // use their label text instead - if (itCuts->getTypeId() == Base::Type::fromName("App::Link")) + if (itCuts->getTypeId() == Base::Type::fromName("App::Link")) { newName = itCuts->Label.getValue(); - else + } + else { newName = itCuts->getNameInDocument(); - newName = newName + "_CutLink"; + } + newName += "_CutLink"; - auto newObject = doc->addObject("App::Link", newName.c_str()); - if (!newObject) { + auto pcLink = dynamic_cast(doc->addObject("App::Link", newName.c_str())); + if (!pcLink) { Base::Console().Error("SectionCut error: 'App::Link' could not be added\n"); return; } - App::Link* pcLink = static_cast(newObject); + // set the object to the created empty link object pcLink->LinkedObject.setValue(itCuts); // we want to get the link at the same position as the original pcLink->LinkTransform.setValue(true); // add link to list to later add this to the compound object - ObjectsListLinks.push_back(newObject); + ObjectsListLinks.push_back(pcLink); // if the object is part of an App::Part container, // the link needs to get the container placement auto parents = itCuts->getInList(); if (!parents.empty()) { for (auto parent : parents) { - if (parent->getTypeId() == Base::Type::fromName("App::Part")) { - App::Part* pcPartParent = static_cast(parent); + if (auto pcPartParent = dynamic_cast(parent)) { auto placement = Base::freecad_dynamic_cast( pcPartParent->getPropertyByName("Placement")); - if (placement) + if (placement) { pcLink->Placement.setValue(placement->getValue()); + } } } } @@ -662,33 +714,36 @@ void SectionCut::startCutting(bool isInitial) auto vpObject = dynamic_cast( Gui::Application::Instance->getViewProvider(itCuts)); if (vpObject) { - if (cutColor != vpObject->ShapeColor.getValue()) + if (cutColor != vpObject->ShapeColor.getValue()) { autoColor = false; - if (cutTransparency != vpObject->Transparency.getValue()) + } + if (cutTransparency != vpObject->Transparency.getValue()) { autoTransparency = false; + } } } } App::DocumentObject* CutCompoundBF = nullptr; Part::Compound* CutCompoundPart = nullptr; - App::DocumentObject* CutCompoundPartObj = nullptr; // specify transparency for the compound // if there was no compound, take the setting for the cut face - if (ui->groupBoxIntersecting->isChecked()) + if (ui->groupBoxIntersecting->isChecked()) { compoundTransparency = ui->BFragTransparencyHS->value(); - if (compoundTransparency == -1) + } + if (compoundTransparency == -1) { compoundTransparency = ui->CutTransparencyHS->value(); + } // create BooleanFragments and fill it if (ui->groupBoxIntersecting->isChecked() && ObjectsListCut.size() > 1) { CutCompoundBF = CreateBooleanFragments(doc); // the BooleanFragment implementation requires to first add at least 2 objects // before any other setting to the BooleanFragment object can be made - App::PropertyLinkList* CutLinkList = - dynamic_cast(CutCompoundBF->getPropertyByName("Objects")); - if (!CutCompoundBF) { + auto CutLinkList = dynamic_cast( + CutCompoundBF ? CutCompoundBF->getPropertyByName("Objects") : nullptr); + if (!CutLinkList) { Base::Console().Error((std::string("SectionCut error: ") + std::string(CompoundName) + std::string(" could not be added\n")).c_str()); return; @@ -708,18 +763,18 @@ void SectionCut::startCutting(bool isInitial) } else { // create Part::Compound and fill it // if there is only one object to be cut, we cannot create a BooleanFragments object - CutCompoundPartObj = doc->addObject("Part::Compound", CompoundName); - if (!CutCompoundPartObj) { + CutCompoundPart = dynamic_cast(doc->addObject("Part::Compound", CompoundName)); + if (!CutCompoundPart) { Base::Console().Error((std::string("SectionCut error: ") + std::string(CompoundName) + std::string(" could not be added\n")).c_str()); return; } - CutCompoundPart = static_cast(CutCompoundPartObj); + // add the link to the compound CutCompoundPart->Links.setValue(ObjectsListLinks); // set the transparency auto vpCompound = dynamic_cast( - Gui::Application::Instance->getViewProvider(CutCompoundPartObj)); + Gui::Application::Instance->getViewProvider(CutCompoundPart)); vpCompound->Transparency.setValue(compoundTransparency); CutCompoundPart->recomputeFeature(); } @@ -730,13 +785,12 @@ void SectionCut::startCutting(bool isInitial) if (object) { object->Visibility.setValue(false); } - object->Visibility.setValue(false); } // the area in which we can cut is the size of the compound // we get its size by its bounding box SbBox3f CompoundBoundingBox = getViewBoundingBox(); - if (CompoundBoundingBox.isEmpty()) { + if (CompoundBoundingBox.isEmpty()) { // NOLINT Base::Console().Error("SectionCut error: the CompoundBoundingBox is empty\n"); return; } @@ -815,19 +869,20 @@ void SectionCut::startCutting(bool isInitial) auto setTransparency = [&](Part::Cut* pcCut) { auto vpCut = dynamic_cast( Gui::Application::Instance->getViewProvider(pcCut)); - if (vpCut) + if (vpCut) { vpCut->Transparency.setValue(compoundTransparency); + } }; if (ui->groupBoxX->isChecked()) { // create a box - auto CutBox = doc->addObject("Part::Box", BoxXName); - if (!CutBox) { + auto pcBox = dynamic_cast(doc->addObject("Part::Box", BoxXName)); + if (!pcBox) { Base::Console().Error( (std::string("SectionCut error: ") + std::string(BoxXName) + std::string(" could not be added\n")).c_str() ); return; } - Part::Box* pcBox = static_cast(CutBox); + // it appears that because of internal rounding errors, the bounding box is sometimes // a bit too small, for example for epplipsoides, thus make the box a bit larger pcBox->Length.setValue(BoundingBoxSize[0] + 1.0); @@ -845,10 +900,13 @@ void SectionCut::startCutting(bool isInitial) // we don't set the value to ui->cutX because this would refresh the cut // which we don't have yet, thus do this later // set the box position - if (!ui->flipX->isChecked()) + if (!ui->flipX->isChecked()) { BoxOriginSet.x = CutPosX - (BoundingBoxSize[0] + 1.0); - else // flipped + } + else { + // flipped BoxOriginSet.x = CutPosX; + } // we made the box 1.0 larger that we can place it 0.5 below the bounding box BoxOriginSet.y = BoundingBoxOrigin[1] - 0.5; BoxOriginSet.z = BoundingBoxOrigin[2] - 0.5; @@ -857,18 +915,20 @@ void SectionCut::startCutting(bool isInitial) setPlaceColorTransparency(pcBox); // create a cut feature - auto CutFeature = doc->addObject("Part::Cut", CutXName); - if (!CutFeature) { + auto pcCut = dynamic_cast(doc->addObject("Part::Cut", CutXName)); + if (!pcCut) { Base::Console().Error( (std::string("SectionCut error: ") + std::string(CutXName) + std::string(" could not be added\n")).c_str() ); return; } - Part::Cut* pcCut = static_cast(CutFeature); - if (ObjectsListCut.size() == 1 || !(ui->groupBoxIntersecting->isChecked())) + + if (ObjectsListCut.size() == 1 || !(ui->groupBoxIntersecting->isChecked())) { pcCut->Base.setValue(CutCompoundPart); - else + } + else { pcCut->Base.setValue(CutCompoundBF); - pcCut->Tool.setValue(CutBox); + } + pcCut->Tool.setValue(pcBox); // we must set the compoundTransparency also for the cut setTransparency(pcCut); @@ -877,10 +937,12 @@ void SectionCut::startCutting(bool isInitial) // recomputing recursively is especially for assemblies very time-consuming // however there must be a final recursicve recompute and we do this at the end // so only recomute recursively if there are no other cuts - if (!ui->groupBoxY->isChecked() && !ui->groupBoxZ->isChecked()) + if (!ui->groupBoxY->isChecked() && !ui->groupBoxZ->isChecked()) { pcCut->recomputeFeature(true); - else + } + else { pcCut->recomputeFeature(false); + } hasBoxX = true; } if (ui->groupBoxY->isChecked()) { @@ -893,13 +955,13 @@ void SectionCut::startCutting(bool isInitial) Refresh::notZValue, Refresh::notXRange, Refresh::YRange, Refresh::notZRange); } - auto CutBox = doc->addObject("Part::Box", BoxYName); - if (!CutBox) { + auto pcBox = dynamic_cast(doc->addObject("Part::Box", BoxYName)); + if (!pcBox) { Base::Console().Error((std::string("SectionCut error: ") + std::string(BoxYName) + std::string(" could not be added\n")).c_str() ); return; } - Part::Box* pcBox = static_cast(CutBox); + pcBox->Length.setValue(BoundingBoxSize[0] + 1.0); pcBox->Width.setValue(BoundingBoxSize[1] + 1.0); pcBox->Height.setValue(BoundingBoxSize[2] + 1.0); @@ -912,40 +974,47 @@ void SectionCut::startCutting(bool isInitial) } // set the box position BoxOriginSet.x = BoundingBoxOrigin[0] - 0.5; - if (!ui->flipY->isChecked()) + if (!ui->flipY->isChecked()) { BoxOriginSet.y = CutPosY - (BoundingBoxSize[1] + 1.0); - else // flipped + } + else { + // flipped BoxOriginSet.y = CutPosY; + } BoxOriginSet.z = BoundingBoxOrigin[2] - 0.5; placement.setPosition(BoxOriginSet); setPlaceColorTransparency(pcBox); - auto CutFeature = doc->addObject("Part::Cut", CutYName); - if (!CutFeature) { + auto pcCut = dynamic_cast(doc->addObject("Part::Cut", CutYName)); + if (!pcCut) { Base::Console().Error((std::string("SectionCut error: ") + std::string(CutYName) + std::string(" could not be added\n")).c_str() ); return; } - Part::Cut* pcCut = static_cast(CutFeature); + // if there is already a cut, we must take it as feature to be cut if (hasBoxX) { pcCut->Base.setValue(doc->getObject(CutXName)); } else { - if (ObjectsListCut.size() == 1 || !(ui->groupBoxIntersecting->isChecked())) + if (ObjectsListCut.size() == 1 || !(ui->groupBoxIntersecting->isChecked())) { pcCut->Base.setValue(CutCompoundPart); - else + } + else { pcCut->Base.setValue(CutCompoundBF); + } } - pcCut->Tool.setValue(CutBox); + pcCut->Tool.setValue(pcBox); setTransparency(pcCut); // set the cut value ui->cutY->setValue(CutPosY); - if (!ui->groupBoxZ->isChecked()) + if (!ui->groupBoxZ->isChecked()) { pcCut->recomputeFeature(true); - else + } + else { pcCut->recomputeFeature(false); + } hasBoxY = true; } if (ui->groupBoxZ->isChecked()) { @@ -955,13 +1024,13 @@ void SectionCut::startCutting(bool isInitial) Refresh::notZValue, Refresh::notXRange, Refresh::notYRange, Refresh::ZRange); } - auto CutBox = doc->addObject("Part::Box", BoxZName); - if (!CutBox) { + auto pcBox = dynamic_cast(doc->addObject("Part::Box", BoxZName)); + if (!pcBox) { Base::Console().Error((std::string("SectionCut error: ") + std::string(BoxZName) + std::string(" could not be added\n")).c_str() ); return; } - Part::Box* pcBox = static_cast(CutBox); + pcBox->Length.setValue(BoundingBoxSize[0] + 1.0); pcBox->Width.setValue(BoundingBoxSize[1] + 1.0); pcBox->Height.setValue(BoundingBoxSize[2] + 1.0); @@ -975,20 +1044,23 @@ void SectionCut::startCutting(bool isInitial) // set the box position BoxOriginSet.x = BoundingBoxOrigin[0] - 0.5; BoxOriginSet.y = BoundingBoxOrigin[1] - 0.5; - if (!ui->flipY->isChecked()) + if (!ui->flipY->isChecked()) { BoxOriginSet.z = CutPosZ - (BoundingBoxSize[2] + 1.0); - else // flipped + } + else { + // flipped BoxOriginSet.z = CutPosZ; + } placement.setPosition(BoxOriginSet); setPlaceColorTransparency(pcBox); - auto CutFeature = doc->addObject("Part::Cut", CutZName); - if (!CutFeature) { + auto pcCut = dynamic_cast(doc->addObject("Part::Cut", CutZName)); + if (!pcCut) { Base::Console().Error( (std::string("SectionCut error: ") + std::string(CutZName) + std::string(" could not be added\n")).c_str() ); return; } - Part::Cut* pcCut = static_cast(CutFeature); + // if there is already a cut, we must take it as feature to be cut if (hasBoxY) { pcCut->Base.setValue(doc->getObject(CutYName)); @@ -997,12 +1069,14 @@ void SectionCut::startCutting(bool isInitial) pcCut->Base.setValue(doc->getObject(CutXName)); } else { - if (ObjectsListCut.size() == 1 || !(ui->groupBoxIntersecting->isChecked())) + if (ObjectsListCut.size() == 1 || !(ui->groupBoxIntersecting->isChecked())) { pcCut->Base.setValue(CutCompoundPart); - else + } + else { pcCut->Base.setValue(CutCompoundBF); + } } - pcCut->Tool.setValue(CutBox); + pcCut->Tool.setValue(pcBox); setTransparency(pcCut); // set the cut value @@ -1015,7 +1089,7 @@ void SectionCut::startCutting(bool isInitial) SectionCut* SectionCut::makeDockWidget(QWidget* parent) { // embed this dialog into a QDockWidget - SectionCut* sectionCut = new SectionCut(parent); + auto sectionCut = new SectionCut(parent); Gui::DockWindowManager* pDockMgr = Gui::DockWindowManager::instance(); // the dialog is designed that you can see the tree, thus put it to the right side QDockWidget *dw = @@ -1039,8 +1113,10 @@ SectionCut::~SectionCut() // make all objects visible that have been visible when the dialog was called // because we made them invisible when we created cuts for (auto& aVisObj : ObjectsListVisible) { - if (aVisObj.getObject())// a formerly visible object might have been deleted + if (aVisObj.getObject()) { + // a formerly visible object might have been deleted aVisObj.getObject()->Visibility.setValue(true); + } } } } @@ -1048,7 +1124,7 @@ SectionCut::~SectionCut() void SectionCut::reject() { QDialog::reject(); - QDockWidget* dw = qobject_cast(parent()); + auto dw = qobject_cast(parent()); if (dw) { dw->deleteLater(); } @@ -1115,9 +1191,10 @@ void SectionCut::onCutXvalueChanged(double val) auto CutBox = doc->getObject(BoxXName); // when the value has been set after resetting the compound bounding box // there is not yet a cut and we do nothing - if (!CutBox) + if (!CutBox) { return; - Part::Box* pcBox = dynamic_cast(CutBox); + } + auto pcBox = dynamic_cast(CutBox); if (!pcBox) { Base::Console().Error((std::string("SectionCut error: ") + std::string(BoxXName) + std::string(" is no Part::Box object. Cannot proceed.\n")).c_str()); @@ -1127,10 +1204,14 @@ void SectionCut::onCutXvalueChanged(double val) Base::Placement placement = pcBox->Placement.getValue(); Base::Vector3d BoxPosition = placement.getPosition(); // change the placement - if (!ui->flipX->isChecked()) + if (!ui->flipX->isChecked()) { BoxPosition.x = ui->cutX->value() - pcBox->Length.getValue(); - else //flipped + } + else { + //flipped BoxPosition.x = ui->cutX->value(); + } + placement.setPosition(BoxPosition); pcBox->Placement.setValue(placement); @@ -1167,16 +1248,16 @@ void SectionCut::onCutXvalueChanged(double val) Refresh::notXRange, Refresh::YRange, Refresh::ZRange); // the value of Y can now be outside or at the limit, in this case reset the value too if ((ui->cutY->value() >= ui->cutY->maximum()) - || (ui->cutY->value() <= ui->cutY->minimum())) + || (ui->cutY->value() <= ui->cutY->minimum())) { refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::YValue, Refresh::ZValue, Refresh::notXRange, Refresh::YRange, Refresh::ZRange); + } // make the SectionCutY visible again CutFeatureY->Visibility.setValue(true); // make SectionCutX invisible again CutObject->Visibility.setValue(false); // recompute the cut - Part::Cut* pcCutY = static_cast(CutFeatureY); - pcCutY->recomputeFeature(true); + CutFeatureY->recomputeFeature(true); } else if (hasBoxZ) { // at least Z // the main cut is Z, no matter if there is a cut in Y @@ -1200,34 +1281,37 @@ void SectionCut::onCutXvalueChanged(double val) Refresh::ZRange); // the value of Y or Z can now be outside or at the limit, in this case reset the value too if ((ui->cutY->value() >= ui->cutY->maximum()) - || (ui->cutY->value() <= ui->cutY->minimum())) + || (ui->cutY->value() <= ui->cutY->minimum())) { refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::YValue, Refresh::notZValue, Refresh::notXRange, Refresh::YRange, Refresh::ZRange); + } if ((ui->cutZ->value() >= ui->cutZ->maximum()) - || (ui->cutZ->value() <= ui->cutZ->minimum())) + || (ui->cutZ->value() <= ui->cutZ->minimum())) { refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::notYValue, Refresh::ZValue, Refresh::notXRange, Refresh::YRange, Refresh::ZRange); + } } - else {// there is no Y cut yet so we can set the Y value too + else { + // there is no Y cut yet so we can set the Y value too refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::YValue, Refresh::notZValue, Refresh::notXRange, Refresh::YRange, Refresh::ZRange); // the value of Z can now be outside or at the limit, in this case reset the value too if ((ui->cutZ->value() >= ui->cutZ->maximum()) - || (ui->cutZ->value() <= ui->cutZ->minimum())) + || (ui->cutZ->value() <= ui->cutZ->minimum())) { refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::YValue, Refresh::ZValue, Refresh::notXRange, Refresh::YRange, Refresh::ZRange); + } } // make the SectionCutZ visible again CutFeatureZ->Visibility.setValue(true); // make SectionCutX invisible again CutObject->Visibility.setValue(false); // recompute the cut - Part::Cut* pcCutZ = static_cast(CutFeatureZ); - pcCutZ->recomputeFeature(true); + CutFeatureZ->recomputeFeature(true); } else { // just X // refresh Y and Z limits + values @@ -1235,7 +1319,7 @@ void SectionCut::onCutXvalueChanged(double val) refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::YValue, Refresh::ZValue, Refresh::notXRange, Refresh::YRange, Refresh::ZRange); // recompute the cut - Part::Cut* pcCut = dynamic_cast(CutObject); + auto pcCut = dynamic_cast(CutObject); if (!pcCut) { Base::Console().Error((std::string("SectionCut error: ") + std::string(CutZName) + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); @@ -1276,9 +1360,10 @@ void SectionCut::onCutYvalueChanged(double val) CutValueHelper(val, ui->cutY, ui->cutYHS); auto CutBox = doc->getObject(BoxYName); - if (!CutBox) + if (!CutBox) { return; - Part::Box* pcBox = dynamic_cast(CutBox); + } + auto pcBox = dynamic_cast(CutBox); if (!pcBox) { Base::Console().Error((std::string("SectionCut error: ") + std::string(BoxYName) + std::string(" is no Part::Box object. Cannot proceed.\n")).c_str()); @@ -1286,10 +1371,14 @@ void SectionCut::onCutYvalueChanged(double val) } Base::Placement placement = pcBox->Placement.getValue(); Base::Vector3d BoxPosition = placement.getPosition(); - if (!ui->flipY->isChecked()) + if (!ui->flipY->isChecked()) { BoxPosition.y = ui->cutY->value() - pcBox->Width.getValue(); - else //flipped + } + else { + //flipped BoxPosition.y = ui->cutY->value(); + } + placement.setPosition(BoxPosition); pcBox->Placement.setValue(placement); @@ -1323,17 +1412,17 @@ void SectionCut::onCutYvalueChanged(double val) Refresh::notXRange, Refresh::notYRange, Refresh::ZRange); // the value of Z can now be outside or at the limit, in this case reset the value too if ((ui->cutZ->value() >= ui->cutZ->maximum()) - || (ui->cutZ->value() <= ui->cutZ->minimum())) + || (ui->cutZ->value() <= ui->cutZ->minimum())) { refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::notYValue, Refresh::ZValue, Refresh::notXRange, Refresh::notYRange, Refresh::ZRange); + } // make the SectionCutZ visible again CutFeatureZ->Visibility.setValue(true); // make SectionCutX invisible again CutObject->Visibility.setValue(false); // recompute the cut - Part::Cut* pcCutZ = static_cast(CutFeatureZ); - pcCutZ->recomputeFeature(true); + CutFeatureZ->recomputeFeature(true); } else { // just Y // refresh Z limits + values @@ -1341,7 +1430,7 @@ void SectionCut::onCutYvalueChanged(double val) refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::notYValue, Refresh::ZValue, Refresh::notXRange, Refresh::notYRange, Refresh::ZRange); // recompute the cut - Part::Cut* pcCut = dynamic_cast(CutObject); + auto pcCut = dynamic_cast(CutObject); if (!pcCut) { Base::Console().Error((std::string("SectionCut error: ") + std::string(CutZName) + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); @@ -1354,14 +1443,17 @@ void SectionCut::onCutYvalueChanged(double val) // if x-limit in box direction is larger than object, reset value to saved limit if (hasBoxX) { auto CutBoxX = doc->getObject(BoxXName); - if (!CutBoxX) + if (!CutBoxX) { return; + } // first store the values - double storedX; - if (!ui->flipX->isChecked()) + double storedX{}; + if (!ui->flipX->isChecked()) { storedX = ui->cutX->minimum(); - else + } + else { storedX = ui->cutX->maximum(); + } // show the cutting box CutBoxX->Visibility.setValue(true); // set new XRange @@ -1372,12 +1464,14 @@ void SectionCut::onCutYvalueChanged(double val) // hide cutting box and compare resultwith stored value CutBoxX->Visibility.setValue(false); if (!ui->flipX->isChecked()) { - if (storedX > ui->cutX->minimum()) + if (storedX > ui->cutX->minimum()) { ui->cutX->setMinimum(storedX); + } } else { - if (storedX < ui->cutX->maximum()) + if (storedX < ui->cutX->maximum()) { ui->cutX->setMaximum(storedX); + } } } } @@ -1411,9 +1505,10 @@ void SectionCut::onCutZvalueChanged(double val) CutValueHelper(val, ui->cutZ, ui->cutZHS); auto CutBox = doc->getObject(BoxZName); - if (!CutBox) + if (!CutBox) { return; - Part::Box* pcBox = dynamic_cast(CutBox); + } + auto pcBox = dynamic_cast(CutBox); if (!pcBox) { Base::Console().Error((std::string("SectionCut error: ") + std::string(BoxZName) + std::string(" is no Part::Box object. Cannot proceed.\n")).c_str()); @@ -1421,10 +1516,13 @@ void SectionCut::onCutZvalueChanged(double val) } Base::Placement placement = pcBox->Placement.getValue(); Base::Vector3d BoxPosition = placement.getPosition(); - if (!ui->flipZ->isChecked()) + if (!ui->flipZ->isChecked()) { BoxPosition.z = ui->cutZ->value() - pcBox->Height.getValue(); - else //flipped + } + else { + //flipped BoxPosition.z = ui->cutZ->value(); + } placement.setPosition(BoxPosition); pcBox->Placement.setValue(placement); @@ -1435,7 +1533,7 @@ void SectionCut::onCutZvalueChanged(double val) startCutting(); return; } - Part::Cut* pcCut = dynamic_cast(CutObject); + auto pcCut = dynamic_cast(CutObject); if (!pcCut) { Base::Console().Error((std::string("SectionCut error: ") + std::string(CutZName) + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); @@ -1449,14 +1547,17 @@ void SectionCut::onCutZvalueChanged(double val) SbBox3f CutBoundingBox; if (hasBoxX) { auto CutBoxX = doc->getObject(BoxXName); - if (!CutBoxX) + if (!CutBoxX) { return; + } // first store the values - double storedX; - if (!ui->flipX->isChecked()) + double storedX{}; + if (!ui->flipX->isChecked()) { storedX = ui->cutX->minimum(); - else + } + else { storedX = ui->cutX->maximum(); + } // show the cutting box CutBoxX->Visibility.setValue(true); // set new XRange @@ -1466,35 +1567,42 @@ void SectionCut::onCutZvalueChanged(double val) // hide cutting box and compare resultwith stored value CutBoxX->Visibility.setValue(false); if (!ui->flipX->isChecked()) { - if (storedX > ui->cutX->minimum()) + if (storedX > ui->cutX->minimum()) { ui->cutX->setMinimum(storedX); + } } else { - if (storedX < ui->cutX->maximum()) + if (storedX < ui->cutX->maximum()) { ui->cutX->setMaximum(storedX); + } } } if (hasBoxY) { auto CutBoxY = doc->getObject(BoxYName); - if (!CutBoxY) + if (!CutBoxY) { return; - double storedY; - if (!ui->flipY->isChecked()) + } + double storedY{}; + if (!ui->flipY->isChecked()) { storedY = ui->cutY->minimum(); - else + } + else { storedY = ui->cutY->maximum(); + } CutBoxY->Visibility.setValue(true); CutBoundingBox = getViewBoundingBox(); refreshCutRanges(CutBoundingBox, Refresh::notXValue, Refresh::notYValue, Refresh::notZValue, Refresh::notXRange, Refresh::YRange, Refresh::notZRange); CutBoxY->Visibility.setValue(false); if (!ui->flipY->isChecked()) { - if (storedY > ui->cutY->minimum()) + if (storedY > ui->cutY->minimum()) { ui->cutY->setMinimum(storedY); + } } else { - if (storedY < ui->cutY->maximum()) + if (storedY < ui->cutY->maximum()) { ui->cutY->setMaximum(storedY); + } } } } @@ -1545,7 +1653,7 @@ void SectionCut::FlipClickedHelper(const char* BoxName) startCutting(); return; } - Part::Box* pcBox = dynamic_cast(CutBox); + auto pcBox = dynamic_cast(CutBox); if (!pcBox) { Base::Console().Error((std::string("SectionCut error: ") + std::string(BoxName) + std::string(" is no Part::Box object. Cannot proceed.\n")).c_str()); @@ -1558,22 +1666,28 @@ void SectionCut::FlipClickedHelper(const char* BoxName) switch (std::string(BoxName).back()) { case 'X': - if (ui->flipX->isChecked()) + if (ui->flipX->isChecked()) { BoxPosition.x = BoxPosition.x + pcBox->Length.getValue(); - else + } + else { BoxPosition.x = BoxPosition.x - pcBox->Length.getValue(); + } break; case 'Y': - if (ui->flipY->isChecked()) + if (ui->flipY->isChecked()) { BoxPosition.y = BoxPosition.y + pcBox->Width.getValue(); - else + } + else { BoxPosition.y = BoxPosition.y - pcBox->Width.getValue(); + } break; case 'Z': - if (ui->flipZ->isChecked()) + if (ui->flipZ->isChecked()) { BoxPosition.z = BoxPosition.z + pcBox->Height.getValue(); - else + } + else { BoxPosition.z = BoxPosition.z - pcBox->Height.getValue(); + } break; } placement.setPosition(BoxPosition); @@ -1584,65 +1698,21 @@ void SectionCut::onFlipXclicked() { FlipClickedHelper(BoxXName); - auto CutObject = doc->getObject(CutXName); - // there should be a cut, but maybe the user deleted it meanwhile - if (!CutObject) { - Base::Console().Warning((std::string("SectionCut warning: there is no ") - + std::string(CutXName) + std::string(", trying to recreate it\n")).c_str()); - // recreate the box - startCutting(); - return; - } - - // if there is another cut, we must recalculate it too - // the hierarchy is always Z->Y->X - if (hasBoxY && !hasBoxZ) { // only Y - auto CutFeatureY = doc->getObject(CutYName); - if (!CutFeatureY) { - Base::Console().Warning((std::string("SectionCut warning: the expected ") - + std::string(CutYName) - + std::string(" is missing, trying to recreate it\n")) - .c_str()); - // recreate the box - startCutting(); - return; + if (auto CutObject = flipCutObject(CutXName)) { + // if there is another cut, we must recalculate it too + // the hierarchy is always Z->Y->X + if (hasBoxY && !hasBoxZ) { + // only Y + CutObject = flipCutObject(CutYName); } - Part::Cut* pcCutY = dynamic_cast(CutFeatureY); - if (!pcCutY) { - Base::Console().Error((std::string("SectionCut error: ") + std::string(CutYName) - + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); - return; + else if ((!hasBoxY && hasBoxZ) || (hasBoxY && hasBoxZ)) { + // at least Z + CutObject = flipCutObject(CutZName); } - pcCutY->recomputeFeature(true); - } - else if ((!hasBoxY && hasBoxZ) || (hasBoxY && hasBoxZ)) { // at least Z - // the main cut is Z, no matter if there is a cut in Y - auto CutFeatureZ = doc->getObject(CutZName); - if (!CutFeatureZ) { - Base::Console().Warning((std::string("SectionCut warning: the expected ") - + std::string(CutZName) - + std::string(" is missing, trying to recreate it\n")) - .c_str()); - // recreate the box - startCutting(); - return; + if (auto cut = dynamic_cast(CutObject)) { + // only do this when there is no other box to save recomputes + cut->recomputeFeature(true); } - Part::Cut* pcCutZ = dynamic_cast(CutFeatureZ); - if (!pcCutZ) { - Base::Console().Error((std::string("SectionCut error: ") + std::string(CutZName) - + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); - return; - } - pcCutZ->recomputeFeature(true); - } - else { // only do this when there is no other box to save recomputes - Part::Cut* pcCut = dynamic_cast(CutObject); - if (!pcCut) { - Base::Console().Error((std::string("SectionCut error: ") + std::string(CutXName) - + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); - return; - } - pcCut->recomputeFeature(true); } } @@ -1650,36 +1720,15 @@ void SectionCut::onFlipYclicked() { FlipClickedHelper(BoxYName); - auto CutObject = doc->getObject(CutYName); - // there should be a cut, but maybe the user deleted it meanwhile - if (!CutObject) { - Base::Console().Warning((std::string("SectionCut warning: there is no ") - + std::string(CutYName) + std::string(", trying to recreate it\n")).c_str()); - // recreate the box - startCutting(); - return; - } - - // if there is another cut, we must recalculate it too - // we only need to check for Z since the hierarchy is always Z->Y->X - if (hasBoxZ) { - auto CutFeatureZ = doc->getObject(CutZName); - Part::Cut* pcCutZ = dynamic_cast(CutFeatureZ); - if (!pcCutZ) { - Base::Console().Error((std::string("SectionCut error: ") + std::string(CutZName) - + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); - return; + if (auto CutObject = flipCutObject(CutYName)) { + // if there is another cut, we must recalculate it too + // we only need to check for Z since the hierarchy is always Z->Y->X + if (hasBoxZ) { + CutObject = findObject(CutZName); } - pcCutZ->recomputeFeature(true); - } - else { - Part::Cut* pcCut = dynamic_cast(CutObject); - if (!pcCut) { - Base::Console().Error((std::string("SectionCut error: ") + std::string(CutYName) - + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); - return; + if (auto cut = dynamic_cast(CutObject)) { + cut->recomputeFeature(true); } - pcCut->recomputeFeature(true); } } @@ -1687,22 +1736,42 @@ void SectionCut::onFlipZclicked() { FlipClickedHelper(BoxZName); - auto CutObject = doc->getObject(CutZName); + if (auto CutObject = flipCutObject(CutZName)) { + CutObject->recomputeFeature(true); + } +} + +Part::Box* SectionCut::findCutBox(const char* name) const +{ + if (auto obj = doc->getObject(name)) { + auto pcBox = dynamic_cast(obj); + if (!pcBox) { + throw Base::RuntimeError("SectionCut error: cut box is incorrectly named, cannot proceed"); + } + + return pcBox; + } + + return nullptr; +} + +App::DocumentObject* SectionCut::findObject(const char* objName) const +{ + return doc ? doc->getObject(objName) : nullptr; +} + +App::DocumentObject* SectionCut::flipCutObject(const char* cutName) +{ + auto CutObject = findObject(cutName); // there should be a cut, but maybe the user deleted it meanwhile if (!CutObject) { Base::Console().Warning((std::string("SectionCut warning: there is no ") - + std::string(CutZName) + std::string(", trying to recreate it\n")).c_str()); + + std::string(cutName) + std::string(", trying to recreate it\n")).c_str()); // recreate the box startCutting(); - return; } - Part::Cut* pcCut = dynamic_cast(CutObject); - if (!pcCut) { - Base::Console().Error((std::string("SectionCut error: ") + std::string(CutZName) - + std::string(" is no Part::Cut object. Cannot proceed.\n")).c_str()); - return; - } - pcCut->recomputeFeature(true); + + return CutObject; } // changes the cutface color @@ -1809,7 +1878,7 @@ void SectionCut::onBFragColorclicked() // sets BooleanFragments color void SectionCut::setBooleanFragmentsColor() { - App::DocumentObject* compoundObject; + App::DocumentObject* compoundObject{}; if (doc->getObject(CompoundName)) { // get the object with the right name compoundObject = doc->getObject(CompoundName); @@ -1819,11 +1888,10 @@ void SectionCut::setBooleanFragmentsColor() return; } // assure it is not a Part::Compound - Part::Compound* pcCompound = dynamic_cast(compoundObject); - Gui::ViewProvider* CompoundBFVP; - if (!pcCompound) { + auto pcCompound = dynamic_cast(compoundObject); + if (!pcCompound && compoundObject) { // check for valid BooleanFragments by accessing its ViewProvider - CompoundBFVP = Gui::Application::Instance->getViewProvider(compoundObject); + auto CompoundBFVP = Gui::Application::Instance->getViewProvider(compoundObject); if (!CompoundBFVP) { Base::Console().Error("SectionCut error: cannot access ViewProvider of cut compound\n"); return; @@ -1943,8 +2011,9 @@ void SectionCut::onRefreshCutPBclicked() ui->groupBoxX->blockSignals(false); } // if there is a cut, disable the button - if (hasBoxX || hasBoxY || hasBoxZ) + if (hasBoxX || hasBoxY || hasBoxZ) { ui->RefreshCutPB->setEnabled(false); + } } SbBox3f SectionCut::getViewBoundingBox() @@ -1955,7 +2024,7 @@ SbBox3f SectionCut::getViewBoundingBox() Base::Console().Error("SectionCut error: there is no active document\n"); return Box; // return an empty box } - Gui::View3DInventor* view = dynamic_cast(docGui->getActiveView()); + auto view = dynamic_cast(docGui->getActiveView()); if (!view) { Base::Console().Error("SectionCut error: could not get the active view\n"); return Box; // return an empty box @@ -1975,22 +2044,24 @@ void SectionCut::refreshCutRanges(SbBox3f BoundingBox, bool forXValue, bool forYValue, bool forZValue, bool forXRange, bool forYRange, bool forZRange) { - if (!BoundingBox.isEmpty()) { + if (!BoundingBox.isEmpty()) { // NOLINT SbVec3f center = BoundingBox.getCenter(); int minDecimals = Base::UnitsApi::getDecimals(); - float lenx, leny, lenz; + float lenx{}; + float leny{}; + float lenz{}; BoundingBox.getSize(lenx, leny, lenz); - int steps = 100; + const int steps = 100; // set the ranges - float rangeMin; // to silence a compiler warning we use a float - float rangeMax; + float rangeMin{}; + float rangeMax{}; if (forXRange) { rangeMin = center[0] - (lenx / 2); rangeMax = center[0] + (lenx / 2); ui->cutX->setRange(rangeMin, rangeMax); // determine the single step values - lenx = lenx / steps; + lenx = lenx / float(steps); int dim = static_cast(log10(lenx)); double singleStep = pow(10.0, dim); ui->cutX->setSingleStep(singleStep); @@ -1999,7 +2070,7 @@ void SectionCut::refreshCutRanges(SbBox3f BoundingBox, rangeMin = center[1] - (leny / 2); rangeMax = center[1] + (leny / 2); ui->cutY->setRange(rangeMin, rangeMax); - leny = leny / steps; + leny = leny / float(steps); int dim = static_cast(log10(leny)); double singleStep = pow(10.0, dim); ui->cutY->setSingleStep(singleStep); @@ -2008,7 +2079,7 @@ void SectionCut::refreshCutRanges(SbBox3f BoundingBox, rangeMin = center[2] - (lenz / 2); rangeMax = center[2] + (lenz / 2); ui->cutZ->setRange(rangeMin, rangeMax); - lenz = lenz / steps; + lenz = lenz / float(steps); int dim = static_cast(log10(lenz)); double singleStep = pow(10.0, dim); ui->cutZ->setSingleStep(singleStep); @@ -2035,6 +2106,7 @@ void SectionCut::refreshCutRanges(SbBox3f BoundingBox, App::DocumentObject* SectionCut::CreateBooleanFragments(App::Document* doc) { + // NOLINTBEGIN // create the object Gui::Command::doCommand(Gui::Command::Doc, "import FreeCAD"); Gui::Command::doCommand(Gui::Command::Doc, "from BOPTools import SplitFeatures"); @@ -2049,6 +2121,8 @@ App::DocumentObject* SectionCut::CreateBooleanFragments(App::Document* doc) return nullptr; } return object; + // NOLINTEND } +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers) #include "moc_SectionCutting.cpp" diff --git a/src/Mod/Part/Gui/SectionCutting.h b/src/Mod/Part/Gui/SectionCutting.h index 6a33d8dad1..567b75fca4 100644 --- a/src/Mod/Part/Gui/SectionCutting.h +++ b/src/Mod/Part/Gui/SectionCutting.h @@ -23,13 +23,19 @@ #ifndef PARTGUI_SECTIONCUTTING_H #define PARTGUI_SECTIONCUTTING_H +#include #include #include +#include #include class QDoubleSpinBox; class QSlider; +namespace Part { +class Box; +} + namespace PartGui { class Ui_SectionCut; @@ -71,6 +77,31 @@ protected Q_SLOTS: public: void reject() override; +private: + void initSpinBoxes(); + void initControls(const Base::BoundBox3d&); + void initXControls(const Base::BoundBox3d&, const std::function&); + void initYControls(const Base::BoundBox3d&, const std::function&); + void initZControls(const Base::BoundBox3d&, const std::function&); + void initCutRanges(); + void setupConnections(); + void tryStartCutting(); + Base::BoundBox3d collectObjects(); + void noDocumentActions(); + void startCutting(bool isInitial = false); + static SbBox3f getViewBoundingBox(); + void refreshCutRanges(SbBox3f, bool forXValue = true, bool forYValue = true, bool forZValue = true, + bool forXRange = true, bool forYRange = true, bool forZRange = true); + void CutValueHelper(double val, QDoubleSpinBox* SpinBox, QSlider* Slider); + void FlipClickedHelper(const char* BoxName); + void changeCutBoxColors(); + App::DocumentObject* CreateBooleanFragments(App::Document* doc); + void setBooleanFragmentsColor(); + Part::Box* findCutBox(const char* name) const; + App::DocumentObject* findObject(const char* objName) const; + void hideCutObjects(); + App::DocumentObject* flipCutObject(const char* cutName); + private: std::unique_ptr ui; std::vector ObjectsListVisible; @@ -79,13 +110,6 @@ private: bool hasBoxY = false; bool hasBoxZ = false; bool hasBoxCustom = false; - void noDocumentActions(); - void startCutting(bool isInitial = false); - SbBox3f getViewBoundingBox(); - void refreshCutRanges(SbBox3f, bool forXValue = true, bool forYValue = true, bool forZValue = true, - bool forXRange = true, bool forYRange = true, bool forZRange = true); - void CutValueHelper(double val, QDoubleSpinBox* SpinBox, QSlider* Slider); - void FlipClickedHelper(const char* BoxName); const char* CompoundName = "SectionCutCompound"; const char* BoxXName = "SectionCutBoxX"; const char* BoxYName = "SectionCutBoxY"; @@ -93,9 +117,6 @@ private: const char* CutXName = "SectionCutX"; const char* CutYName = "SectionCutY"; const char* CutZName = "SectionCutZ"; - void changeCutBoxColors(); - App::DocumentObject* CreateBooleanFragments(App::Document* doc); - void setBooleanFragmentsColor(); }; } // namespace PartGui diff --git a/src/Mod/Path/Path/Post/UtilsArguments.py b/src/Mod/Path/Path/Post/UtilsArguments.py index b7559aa918..e91a0378cf 100644 --- a/src/Mod/Path/Path/Post/UtilsArguments.py +++ b/src/Mod/Path/Path/Post/UtilsArguments.py @@ -343,12 +343,6 @@ def init_shared_values(values: Values): # values["COMMENT_SYMBOL"] = "(" # - # Variables storing the current position for the drill_translate routine. - # - values["CURRENT_X"] = 0.0 - values["CURRENT_Y"] = 0.0 - values["CURRENT_Z"] = 0.0 - # # Default axis precision for metric is 3 digits after the decimal point. # (see http://linuxcnc.org/docs/2.7/html/gcode/overview.html#_g_code_best_practices) # @@ -371,11 +365,6 @@ def init_shared_values(values: Values): # values["DRILL_CYCLES_TO_TRANSLATE"] = ["G73", "G81", "G82", "G83"] # - # The default value of drill retractations (CURRENT_Z). - # The other possible value is G99. - # - values["DRILL_RETRACT_MODE"] = "G98" - # # If this is set to True, then M7, M8, and M9 commands # to enable/disable coolant will be output. # diff --git a/src/Mod/Path/PathTests/TestRefactoredTestPostGCodes.py b/src/Mod/Path/PathTests/TestRefactoredTestPostGCodes.py index 24f44d168f..4b8ddc9915 100644 --- a/src/Mod/Path/PathTests/TestRefactoredTestPostGCodes.py +++ b/src/Mod/Path/PathTests/TestRefactoredTestPostGCodes.py @@ -123,12 +123,18 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): """Test G0 command Generation.""" self.compare_third_line( "G0 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - "G0 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000", + ( + "G0 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000" + ), "", ) self.compare_third_line( "G00 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - "G00 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000", + ( + "G00 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000" + ), "", ) @@ -136,23 +142,35 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): """Test G1 command Generation.""" self.compare_third_line( "G1 X10 Y20 Z30 A40 B50 C60 U70 V80 W90 F1.23456", - "G1 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000 F74.074", + ( + "G1 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000 F74.074" + ), "", ) self.compare_third_line( "G01 X10 Y20 Z30 A40 B50 C60 U70 V80 W90 F1.23456", - "G01 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000 F74.074", + ( + "G01 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000 F74.074" + ), "", ) # Test argument order self.compare_third_line( "G1 F1.23456 Z30 V80 C60 W90 X10 B50 U70 Y20 A40", - "G1 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000 F74.074", + ( + "G1 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000 F74.074" + ), "", ) self.compare_third_line( "G1 X10 Y20 Z30 A40 B50 C60 U70 V80 W90 F1.23456", - "G1 X0.3937 Y0.7874 Z1.1811 A1.5748 B1.9685 C2.3622 U2.7559 V3.1496 W3.5433 F2.9163", + ( + "G1 X0.3937 Y0.7874 Z1.1811 A1.5748 B1.9685 C2.3622 " + "U2.7559 V3.1496 W3.5433 F2.9163" + ), "--inches", ) @@ -311,7 +329,10 @@ class TestRefactoredTestPostGCodes(PathTestUtils.PathTestBase): self.compare_third_line("G28", "G28", "") self.compare_third_line( "G28 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - "G28 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000", + ( + "G28 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000" + ), "", ) @@ -1233,7 +1254,10 @@ G90 """Test G92 command Generation.""" self.compare_third_line( "G92 X10 Y20 Z30 A40 B50 C60 U70 V80 W90", - "G92 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 U70.000 V80.000 W90.000", + ( + "G92 X10.000 Y20.000 Z30.000 A40.000 B50.000 C60.000 " + "U70.000 V80.000 W90.000" + ), "", ) diff --git a/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp b/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp index eefa60b724..383a412da5 100644 --- a/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp +++ b/src/Mod/Spreadsheet/Gui/AppSpreadsheetGui.cpp @@ -111,7 +111,9 @@ PyMOD_INIT_FUNC(SpreadsheetGui) // instantiating the commands CreateSpreadsheetCommands(); +#if defined(Q_OS_WIN32) QAccessible::installFactory(SpreadsheetGui::SheetTableViewAccessibleInterface::ifactory); +#endif SpreadsheetGui::ViewProviderSheet::init(); SpreadsheetGui::ViewProviderSheetPython::init(); diff --git a/src/Mod/TechDraw/Gui/QGIEdge.cpp b/src/Mod/TechDraw/Gui/QGIEdge.cpp index 0e69c79982..65e559897a 100644 --- a/src/Mod/TechDraw/Gui/QGIEdge.cpp +++ b/src/Mod/TechDraw/Gui/QGIEdge.cpp @@ -32,9 +32,14 @@ #include #include #include +#include +#include +#include #include "QGIEdge.h" +#include "QGIViewPart.h" #include "PreferencesGui.h" +#include "TaskLineDecor.h" using namespace TechDrawGui; @@ -51,7 +56,8 @@ QGIEdge::QGIEdge(int index) : setFill(Qt::NoBrush); } -//NOTE this refers to Qt cosmetic lines +// NOTE this refers to Qt cosmetic lines (a line with minimum width), +// not FreeCAD cosmetic lines void QGIEdge::setCosmetic(bool state) { // Base::Console().Message("QGIE::setCosmetic(%d)\n", state); @@ -113,3 +119,15 @@ QPainterPath QGIEdge::shape() const outline = stroker.createStroke(path()); return outline; } + +void QGIEdge::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + Q_UNUSED(event) + QGIView *parent = dynamic_cast(parentItem()); + if (parent && parent->getViewObject() && parent->getViewObject()->isDerivedFrom(TechDraw::DrawViewPart::getClassTypeId())) { + TechDraw::DrawViewPart *baseFeat = static_cast(parent->getViewObject()); + std::vector edgeName(1, DrawUtil::makeGeomName("Edge", getProjIndex())); + + Gui::Control().showDialog(new TaskDlgLineDecor(baseFeat, edgeName)); + } +} diff --git a/src/Mod/TechDraw/Gui/QGIEdge.h b/src/Mod/TechDraw/Gui/QGIEdge.h index d8ed9b974b..1bc54dc2bc 100644 --- a/src/Mod/TechDraw/Gui/QGIEdge.h +++ b/src/Mod/TechDraw/Gui/QGIEdge.h @@ -54,6 +54,9 @@ public: double getEdgeFuzz(void) const; protected: + + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; + int projIndex; //index of edge in Projection. must exist. bool isCosmetic; diff --git a/src/Mod/TechDraw/Gui/QGIPrimPath.cpp b/src/Mod/TechDraw/Gui/QGIPrimPath.cpp index 1e9845269a..63679534ca 100644 --- a/src/Mod/TechDraw/Gui/QGIPrimPath.cpp +++ b/src/Mod/TechDraw/Gui/QGIPrimPath.cpp @@ -59,7 +59,8 @@ QGIPrimPath::QGIPrimPath(): m_colOverride = false; m_colNormal = getNormalColor(); m_colCurrent = m_colNormal; - m_styleCurrent = Qt::SolidLine; + m_styleNormal = Qt::SolidLine; + m_styleCurrent = m_styleNormal; m_pen.setStyle(m_styleCurrent); m_capStyle = prefCapStyle(); m_pen.setCapStyle(m_capStyle); @@ -207,6 +208,7 @@ void QGIPrimPath::setWidth(double w) void QGIPrimPath::setStyle(Qt::PenStyle s) { // Base::Console().Message("QGIPP::setStyle(QTPS: %d)\n", s); + m_styleNormal = s; m_styleCurrent = s; } @@ -214,6 +216,7 @@ void QGIPrimPath::setStyle(int s) { // Base::Console().Message("QGIPP::setStyle(int: %d)\n", s); m_styleCurrent = static_cast(s); + m_styleNormal = static_cast(s); } void QGIPrimPath::setNormalColor(QColor c) @@ -308,6 +311,7 @@ void QGIPrimPath::paint ( QPainter * painter, const QStyleOptionGraphicsItem * o m_pen.setWidthF(m_width); m_pen.setColor(m_colCurrent); + m_pen.setStyle(m_styleCurrent); setPen(m_pen); m_brush.setColor(m_fillColorCurrent); diff --git a/src/Mod/TechDraw/Gui/QGIViewPart.cpp b/src/Mod/TechDraw/Gui/QGIViewPart.cpp index f7b7e13b6d..fe4e60d42a 100644 --- a/src/Mod/TechDraw/Gui/QGIViewPart.cpp +++ b/src/Mod/TechDraw/Gui/QGIViewPart.cpp @@ -289,8 +289,6 @@ void QGIViewPart::drawAllEdges() item->setNormalColor(PreferencesGui::getAccessibleQColor(PreferencesGui::normalQColor())); item->setStyle(Qt::SolidLine); if ((*itGeom)->getCosmetic()) { - item->setCosmetic(true); - // cosmetic edge - format appropriately int source = (*itGeom)->source(); if (source == COSMETICEDGE) { diff --git a/src/Mod/TechDraw/Gui/TaskDetail.cpp b/src/Mod/TechDraw/Gui/TaskDetail.cpp index 6ad3622b98..18307fc2c1 100644 --- a/src/Mod/TechDraw/Gui/TaskDetail.cpp +++ b/src/Mod/TechDraw/Gui/TaskDetail.cpp @@ -435,7 +435,7 @@ void TaskDetail::createDetail() Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Create Detail View")); const std::string objectName{"Detail"}; - std::string m_detailName = m_doc->getUniqueObjectName(objectName.c_str()); + m_detailName = m_doc->getUniqueObjectName(objectName.c_str()); std::string generatedSuffix {m_detailName.substr(objectName.length())}; Gui::Command::doCommand(Command::Doc, "App.activeDocument().addObject('TechDraw::DrawViewDetail', '%s')", @@ -444,13 +444,12 @@ void TaskDetail::createDetail() Gui::Command::doCommand(Command::Doc, "App.activeDocument().%s.translateLabel('DrawViewDetail', 'Detail', '%s')", m_detailName.c_str(), m_detailName.c_str()); - App::DocumentObject *docObj = m_doc->getObject(m_detailName.c_str()); + App::DocumentObject *docObj = m_baseFeat->getDocument()->getObject(m_detailName.c_str()); TechDraw::DrawViewDetail* dvd = dynamic_cast(docObj); if (!dvd) { throw Base::TypeError("TaskDetail - new detail view not found\n"); } m_detailFeat = dvd; - dvd->Source.setValues(getBaseFeat()->Source.getValues()); Gui::Command::doCommand(Command::Doc, "App.activeDocument().%s.BaseView = App.activeDocument().%s", @@ -564,8 +563,8 @@ DrawViewDetail* TaskDetail::getDetailFeat() { // Base::Console().Message("TD::getDetailFeat()\n"); - if (m_doc) { - App::DocumentObject* detailObj = m_doc->getObject(m_detailName.c_str()); + if (m_baseFeat) { + App::DocumentObject* detailObj = m_baseFeat->getDocument()->getObject(m_detailName.c_str()); if (detailObj) { return static_cast(detailObj); } diff --git a/src/Mod/TechDraw/Gui/TaskLineDecor.cpp b/src/Mod/TechDraw/Gui/TaskLineDecor.cpp index cb9b9a8679..13870a408a 100644 --- a/src/Mod/TechDraw/Gui/TaskLineDecor.cpp +++ b/src/Mod/TechDraw/Gui/TaskLineDecor.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include #include "TaskLineDecor.h" @@ -56,15 +55,16 @@ TaskLineDecor::TaskLineDecor(TechDraw::DrawViewPart* partFeat, m_edges(edgeNames), m_apply(true) { + initializeRejectArrays(); + getDefaults(); ui->setupUi(this); + initUi(); connect(ui->cb_Style, qOverload(&QComboBox::currentIndexChanged), this, &TaskLineDecor::onStyleChanged); connect(ui->cc_Color, &ColorButton::changed, this, &TaskLineDecor::onColorChanged); connect(ui->dsb_Weight, qOverload(&QuantitySpinBox::valueChanged), this, &TaskLineDecor::onWeightChanged); connect(ui->cb_Visible, qOverload(&QComboBox::currentIndexChanged), this, &TaskLineDecor::onVisibleChanged); - - initUi(); } TaskLineDecor::~TaskLineDecor() @@ -94,6 +94,66 @@ void TaskLineDecor::initUi() ui->cb_Visible->setCurrentIndex(m_visible); } +TechDraw::LineFormat *TaskLineDecor::getFormatAccessPtr(const std::string &edgeName, std::string *newFormatTag) +{ + BaseGeomPtr bg = m_partFeat->getEdge(edgeName); + if (bg) { + if (bg->getCosmetic()) { + if (bg->source() == SourceType::COSEDGE) { + TechDraw::CosmeticEdge *ce = m_partFeat->getCosmeticEdgeBySelection(edgeName); + if (ce) { + return &ce->m_format; + } + } + else if (bg->source() == SourceType::CENTERLINE) { + TechDraw::CenterLine *cl = m_partFeat->getCenterLineBySelection(edgeName); + if (cl) { + return &cl->m_format; + } + } + } + else { + TechDraw::GeomFormat *gf = m_partFeat->getGeomFormatBySelection(edgeName); + if (gf) { + return &gf->m_format; + } + else { + ViewProviderViewPart *viewPart = dynamic_cast(QGIView::getViewProvider(m_partFeat)); + if (viewPart) { + TechDraw::LineFormat lineFormat(Qt::SolidLine, viewPart->LineWidth.getValue(), LineFormat::getDefEdgeColor(), true); + TechDraw::GeomFormat geomFormat(DrawUtil::getIndexFromName(edgeName), lineFormat); + + std::string formatTag = m_partFeat->addGeomFormat(&geomFormat); + if (newFormatTag) { + *newFormatTag = formatTag; + } + + return &m_partFeat->getGeomFormat(formatTag)->m_format; + } + } + } + } + return nullptr; +} + +void TaskLineDecor::initializeRejectArrays() +{ + m_originalFormats.resize(m_edges.size()); + m_createdFormatTags.resize(m_edges.size()); + + for (size_t i = 0; i < m_edges.size(); ++i) { + std::string newTag; + TechDraw::LineFormat *accessPtr = getFormatAccessPtr(m_edges[i], &newTag); + + if (accessPtr) { + m_originalFormats[i] = *accessPtr; + if (!newTag.empty()) { + m_createdFormatTags[i] = newTag; + } + } + } +} + void TaskLineDecor::getDefaults() { // Base::Console().Message("TLD::getDefaults()\n"); @@ -103,44 +163,12 @@ void TaskLineDecor::getDefaults() m_visible = true; //set defaults to format of 1st edge - if (!m_edges.empty()) { - int num = DrawUtil::getIndexFromName(m_edges.front()); - BaseGeomPtr bg = m_partFeat->getGeomByIndex(num); - if (bg) { - if (bg->getCosmetic()) { - if (bg->source() == 1) { - TechDraw::CosmeticEdge* ce = m_partFeat->getCosmeticEdgeBySelection(m_edges.front()); - m_style = ce->m_format.m_style; - m_color = ce->m_format.m_color; - m_weight = ce->m_format.m_weight; - m_visible = ce->m_format.m_visible; - } else if (bg->source() == 2) { -// TechDraw::CenterLine* cl = m_partFeat->getCenterLine(bg->getCosmeticTag); - TechDraw::CenterLine* cl = m_partFeat->getCenterLineBySelection(m_edges.front()); - m_style = cl->m_format.m_style; - m_color = cl->m_format.m_color; - m_weight = cl->m_format.m_weight; - m_visible = cl->m_format.m_visible; - } - } else { - TechDraw::GeomFormat* gf = m_partFeat->getGeomFormatBySelection(num); - if (gf) { - m_style = gf->m_format.m_style; - m_color = gf->m_format.m_color; - m_weight = gf->m_format.m_weight; - m_visible = gf->m_format.m_visible; - } else { - Gui::ViewProvider* vp = QGIView::getViewProvider(m_partFeat); - auto partVP = dynamic_cast(vp); - if (partVP) { - m_weight = partVP->LineWidth.getValue(); - m_style = Qt::SolidLine; // = 1 - m_color = LineFormat::getDefEdgeColor(); - m_visible = true; - } - } - } - } + if (!m_originalFormats.empty()) { + LineFormat &lf = m_originalFormats.front(); + m_style = lf.m_style; + m_color = lf.m_color; + m_weight = lf.m_weight; + m_visible = lf.m_visible; } } @@ -176,42 +204,12 @@ void TaskLineDecor::applyDecorations() { // Base::Console().Message("TLD::applyDecorations()\n"); for (auto& e: m_edges) { - int num = DrawUtil::getIndexFromName(e); - BaseGeomPtr bg = m_partFeat->getGeomByIndex(num); - if (bg) { - if (bg->getCosmetic()) { - if (bg->source() == 1) { - TechDraw::CosmeticEdge* ce = m_partFeat->getCosmeticEdgeBySelection(e); - ce->m_format.m_style = m_style; - ce->m_format.m_color = m_color; - ce->m_format.m_weight = m_weight; - ce->m_format.m_visible = m_visible; - } else if (bg->source() == 2) { -// TechDraw::CenterLine* cl = m_partFeat->getCenterLine(bg->getCosmeticTag()); - TechDraw::CenterLine* cl = m_partFeat->getCenterLineBySelection(e); - cl->m_format.m_style = m_style; - cl->m_format.m_color = m_color; - cl->m_format.m_weight = m_weight; - cl->m_format.m_visible = m_visible; - } - } else { - TechDraw::GeomFormat* gf = m_partFeat->getGeomFormatBySelection(num); - if (gf) { - gf->m_format.m_style = m_style; - gf->m_format.m_color = m_color; - gf->m_format.m_weight = m_weight; - gf->m_format.m_visible = m_visible; - } else { - TechDraw::LineFormat fmt(m_style, - m_weight, - m_color, - m_visible); - TechDraw::GeomFormat* newGF = new TechDraw::GeomFormat(num, - fmt); -// int idx = - m_partFeat->addGeomFormat(newGF); - } - } + LineFormat *lf = getFormatAccessPtr(e); + if (lf) { + lf->m_style = m_style; + lf->m_color = m_color; + lf->m_weight = m_weight; + lf->m_visible = m_visible; } } } @@ -242,6 +240,21 @@ bool TaskLineDecor::reject() if (!doc) return false; + for (size_t i = 0; i < m_originalFormats.size(); ++i) { + std::string &formatTag = m_createdFormatTags[i]; + if (formatTag.empty()) { + LineFormat *lf = getFormatAccessPtr(m_edges[i]); + if (lf) { + *lf = m_originalFormats[i]; + } + } + else { + m_partFeat->removeGeomFormat(formatTag); + } + } + + m_partFeat->requestPaint(); + Gui::Command::doCommand(Gui::Command::Gui, "Gui.ActiveDocument.resetEdit()"); return false; } diff --git a/src/Mod/TechDraw/Gui/TaskLineDecor.h b/src/Mod/TechDraw/Gui/TaskLineDecor.h index 9c58640c1a..c773a1a21e 100644 --- a/src/Mod/TechDraw/Gui/TaskLineDecor.h +++ b/src/Mod/TechDraw/Gui/TaskLineDecor.h @@ -26,7 +26,7 @@ #include #include #include - +#include namespace App { @@ -62,6 +62,10 @@ protected Q_SLOTS: protected: void changeEvent(QEvent *e) override; void initUi(); + + TechDraw::LineFormat *getFormatAccessPtr(const std::string &edgeName, std::string *newFormatTag = nullptr); + void initializeRejectArrays(); + void applyDecorations(); void getDefaults(); @@ -69,6 +73,10 @@ private: std::unique_ptr ui; TechDraw::DrawViewPart* m_partFeat; std::vector m_edges; + + std::vector m_originalFormats; + std::vector m_createdFormatTags; + int m_style; App::Color m_color; double m_weight; diff --git a/src/Tools/xmlformat/CMakeLists.txt b/src/Tools/xmlformat/CMakeLists.txt new file mode 100644 index 0000000000..b06e4d0798 --- /dev/null +++ b/src/Tools/xmlformat/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) + +project(xmlformat LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Xml REQUIRED) +find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Xml REQUIRED) + +add_executable(xmlformat + main.cpp +) +target_link_libraries(xmlformat Qt${QT_VERSION_MAJOR}::Core + Qt${QT_VERSION_MAJOR}::Xml) diff --git a/src/Tools/xmlformat/main.cpp b/src/Tools/xmlformat/main.cpp new file mode 100644 index 0000000000..3948a27899 --- /dev/null +++ b/src/Tools/xmlformat/main.cpp @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later + +/*************************************************************************** + * Copyright (c) 2023 Werner Mayer * + * * + * This file is part of FreeCAD. * + * * + * FreeCAD is free software: you can redistribute it and/or modify it * + * under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation, either version 2.1 of the * + * License, or (at your option) any later version. * + * * + * FreeCAD 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 * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with FreeCAD. If not, see * + * . * + * * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + QCoreApplication app(argc, argv); + QStringList args = QCoreApplication::arguments(); + if (args.size() != 2) { + std::cerr << "Requires input file\n"; + return -1; + } + + QFile file(args[1]); + if (!file.open(QFile::ReadOnly)) { + std::cerr << "Failed to read file\n"; + return -1; + } + + QXmlStreamReader reader(file.readAll()); + file.close(); + + if (!file.open(QFile::WriteOnly)) { + std::cerr << "Failed to write file\n"; + return -1; + } + + QXmlStreamWriter writer(&file); + writer.setAutoFormatting(true); + writer.setAutoFormattingIndent(4); + + auto findAttr = [](const QXmlStreamAttributes& attr, const QString& name) { + for (int i = 0; i < attr.size(); ++i) { + if (attr.at(i).name() == name) { + return i; + } + } + + return -1; + }; + + // ---------------------- + + auto sortAttr = [&findAttr](QXmlStreamAttributes& attr) { + QStringList list = {"Name", + "Namespace", + "Twin", + "TwinPointer", + "PythonName", + "FatherInclude", + "Include", + "Father", + "FatherNamespace"}; + QXmlStreamAttributes sorted; + for (const auto& it : list) { + int index = findAttr(attr, it); + if (index > -1) { + sorted.append(attr.at(index)); + attr.remove(index); + } + } + + // add the rest + for (const auto& it : qAsConst(attr)) { + sorted.append(it); + } + + return sorted; + }; + + // ---------------------- + + while (!reader.atEnd()) { + reader.readNext(); + if (reader.isStartElement() && reader.name() == QLatin1String("PythonExport")) { + QXmlStreamAttributes attr = reader.attributes(); + attr = sortAttr(attr); + + writer.writeStartElement(QString("PythonExport")); + for (int i = 0; i < attr.size(); ++i) { + file.write("\n "); + writer.writeAttribute(attr.at(i)); + } + } + else if (reader.isStartElement() && reader.name() == QLatin1String("UserDocu")) { + QString text = reader.readElementText().trimmed(); + text.replace("\t", " "); + writer.writeTextElement(QString("UserDocu"), text); + } + else if (!reader.isWhitespace()) { + writer.writeCurrentToken(reader); + } + } + + file.close(); + + return 0; +}