diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp
index 66b68c3abd..3a4b9cea2f 100644
--- a/src/Gui/View3DInventorViewer.cpp
+++ b/src/Gui/View3DInventorViewer.cpp
@@ -91,6 +91,7 @@
#include
#include
#include
+#include
#include
#include
@@ -2657,8 +2658,76 @@ SbVec2f View3DInventorViewer::getNormalizedPosition(const SbVec2s& pnt) const
return {pX, pY};
}
-SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt,
- const Base::Placement& plc) const
+Base::BoundBox2d View3DInventorViewer::getViewportOnXYPlaneOfPlacement(Base::Placement plc) const
+{
+ auto projBBox = Base::BoundBox3d();
+ projBBox.SetVoid();
+
+ SoCamera* pCam = this->getSoRenderManager()->getCamera();
+
+ if (!pCam) {
+ // Return empty box.
+ return Base::BoundBox2d(0, 0, 0, 0);
+ }
+
+ Base::Vector3d pos = plc.getPosition();
+ Base::Rotation rot = plc.getRotation();
+
+ // Transform the plane LCS into the global one.
+ Base::Vector3d zAxis(0, 0, 1);
+ rot.multVec(zAxis, zAxis);
+
+ // Get the position and convert Base::Vector3d to SbVec3f
+ SbVec3f planeNormal(zAxis.x, zAxis.y, zAxis.z);
+ SbVec3f planePosition(pos.x, pos.y, pos.z);
+ SbPlane xyPlane(planeNormal, planePosition);
+
+ const SbViewportRegion& vp = this->getSoRenderManager()->getViewportRegion();
+ SbViewVolume vol = pCam->getViewVolume();
+
+ float fRatio = vp.getViewportAspectRatio();
+ float dX, dY;
+ vp.getViewportSize().getValue(dX, dY);
+
+ // Projects a pair of normalized coordinates on the XY plane.
+ auto projectPoint =
+ [&](float x, float y) {
+ if (fRatio > 1.f) {
+ x = (x - 0.5f * dX) * fRatio + 0.5f * dX;
+ }
+ else if (fRatio < 1.f) {
+ y = (y - 0.5f * dY) / fRatio + 0.5f * dY;
+ }
+
+ SbLine line;
+ vol.projectPointToLine(SbVec2f(x, y), line);
+
+ SbVec3f pt;
+ // Intersection point on the XY plane.
+ if (!xyPlane.intersect(line, pt)) {
+ return;
+ }
+
+ projBBox.Add(Base::convertTo(pt));
+ };
+
+ // Project the four corners of the viewport plane.
+ projectPoint(0.f, 0.f);
+ projectPoint(1.f, 0.f);
+ projectPoint(0.f, 1.f);
+ projectPoint(1.f, 1.f);
+
+ if (!projBBox.IsValid()) {
+ // Return empty box.
+ return Base::BoundBox2d(0, 0, 0, 0);
+ }
+
+ plc.invert();
+ Base::ViewOrthoProjMatrix proj(plc.toMatrix());
+ return projBBox.ProjectBox(&proj);
+}
+
+SbVec3f View3DInventorViewer::getPointOnXYPlaneOfPlacement(const SbVec2s& pnt, const Base::Placement& plc) const
{
SbVec2f pnt2d = getNormalizedPosition(pnt);
SoCamera* pCam = this->getSoRenderManager()->getCamera();
diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h
index dfa91ca3de..1a520e616c 100644
--- a/src/Gui/View3DInventorViewer.h
+++ b/src/Gui/View3DInventorViewer.h
@@ -67,6 +67,10 @@ class SoClipPlane;
namespace Quarter = SIM::Coin3D::Quarter;
+namespace Base {
+ class BoundBox2d;
+}
+
namespace Gui {
class ViewProvider;
@@ -311,6 +315,9 @@ public:
/** Returns the 3d point on the XY plane of a placement to the given 2d point. */
SbVec3f getPointOnXYPlaneOfPlacement(const SbVec2s&, const Base::Placement&) const;
+ /** Returns the bounding box on the XY plane of a placement to the given 2d point. */
+ Base::BoundBox2d getViewportOnXYPlaneOfPlacement(Base::Placement plc) const;
+
/** Returns the 2d coordinates on the viewport to the given 3d point. */
SbVec2s getPointOnViewport(const SbVec3f&) const;
diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp
index e29026c9dd..28660f5b64 100644
--- a/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp
+++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.cpp
@@ -808,8 +808,6 @@ void EditModeCoinManager::processGeometryConstraintsInformationOverlay(
processGeometryInformationOverlay(geolistfacade);
- updateAxesLength();
-
pEditModeConstraintCoinManager->processConstraints(geolistfacade);
}
@@ -852,22 +850,18 @@ void EditModeCoinManager::processGeometryInformationOverlay(const GeoListFacade&
overlayParameters.visibleInformationChanged = false; // just updated
}
-void EditModeCoinManager::updateAxesLength()
+void EditModeCoinManager::updateAxesLength(const Base::BoundBox2d& bb)
{
auto zCrossH = ViewProviderSketchCoinAttorney::getViewOrientationFactor(viewProvider)
* drawingParameters.zCross;
- editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(
- 0,
- SbVec3f(-analysisResults.boundingBoxMagnitudeOrder, 0.0f, zCrossH));
- editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(
- 1,
- SbVec3f(analysisResults.boundingBoxMagnitudeOrder, 0.0f, zCrossH));
- editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(
- 2,
- SbVec3f(0.0f, -analysisResults.boundingBoxMagnitudeOrder, zCrossH));
- editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(
- 3,
- SbVec3f(0.0f, analysisResults.boundingBoxMagnitudeOrder, zCrossH));
+ editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(0,
+ SbVec3f(bb.MinX, 0.0f, zCrossH));
+ editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(1,
+ SbVec3f(bb.MaxX, 0.0f, zCrossH));
+ editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(2,
+ SbVec3f(0.0f, bb.MinY, zCrossH));
+ editModeScenegraphNodes.RootCrossCoordinate->point.set1Value(3,
+ SbVec3f(0.0f, bb.MaxY, zCrossH));
}
void EditModeCoinManager::updateColor()
diff --git a/src/Mod/Sketcher/Gui/EditModeCoinManager.h b/src/Mod/Sketcher/Gui/EditModeCoinManager.h
index 338d983452..2d06a995a6 100644
--- a/src/Mod/Sketcher/Gui/EditModeCoinManager.h
+++ b/src/Mod/Sketcher/Gui/EditModeCoinManager.h
@@ -44,6 +44,8 @@ class Vector3;
class Vector2d;
+class BoundBox2d;
+
class Placement;
} // namespace Base
@@ -256,6 +258,9 @@ public:
void setConstraintSelectability(bool enabled = true);
//@}
+ // Updates the Axes extension to span the specified area.
+ void updateAxesLength(const Base::BoundBox2d& bb);
+
private:
// This function populates the coin nodes with the information of the current geometry
void processGeometry(const GeoListFacade& geolistfacade);
@@ -265,9 +270,6 @@ private:
// parallel.
void processGeometryInformationOverlay(const GeoListFacade& geolistfacade);
- // updates the Axes length to extend beyond the calculated bounding box magnitude
- void updateAxesLength();
-
// updates the parameters to be used for the Overlay information layer
void updateOverlayParameters();
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
index d70834bb13..55a91adafa 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp
@@ -3459,8 +3459,10 @@ void ViewProviderSketch::setEditViewer(Gui::View3DInventorViewer* viewer, int Mo
viewer->setupEditingRoot();
- cameraSensor.setData(new VPRender {this, viewer->getSoRenderManager()});
- cameraSensor.attach(viewer->getSoRenderManager()->getSceneGraph());
+ auto *camSensorData = new VPRender {this, viewer->getSoRenderManager()};
+ cameraSensor.setData(camSensorData);
+ cameraSensor.setDeleteCallback(&ViewProviderSketch::camSensDeleteCB, camSensorData);
+ cameraSensor.attach(viewer->getCamera());
}
void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer)
@@ -3468,6 +3470,7 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer)
auto dataPtr = static_cast(cameraSensor.getData());
delete dataPtr;
cameraSensor.setData(nullptr);
+ cameraSensor.setDeleteCallback(nullptr, nullptr);
cameraSensor.detach();
viewer->removeGraphicsItem(rubberband.get());
@@ -3475,6 +3478,22 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer)
viewer->setSelectionEnabled(true);
}
+void ViewProviderSketch::camSensDeleteCB(void* data, SoSensor *s)
+{
+ auto *proxyVPrdr = static_cast(data);
+ if (!proxyVPrdr)
+ return;
+
+ // The camera object the observer was attached to is gone, try to re-attach the sensor
+ // to the new camera.
+ // This happens i.e. when the user switches the camera type from orthographic to
+ // perspective.
+ SoCamera *camera = proxyVPrdr->renderMgr->getCamera();
+ if (camera) {
+ static_cast(s)->attach(camera);
+ }
+}
+
void ViewProviderSketch::camSensCB(void* data, SoSensor*)
{
VPRender* proxyVPrdr = static_cast(data);
@@ -3516,6 +3535,15 @@ void ViewProviderSketch::onCameraChanged(SoCamera* cam)
Base::Interpreter().runStringObject(cmdStr.toLatin1());
}
+ // Stretch the axes to cover the whole viewport.
+ Gui::View3DInventor* view = qobject_cast(this->getActiveView());
+ if (view) {
+ Base::Placement plc = getEditingPlacement();
+ const Base::BoundBox2d vpBBox = view->getViewer()
+ ->getViewportOnXYPlaneOfPlacement(plc);
+ editCoinManager->updateAxesLength(vpBBox);
+ }
+
drawGrid(true);
}
diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h
index ae5b272690..0ceb339efd 100644
--- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h
+++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h
@@ -717,7 +717,8 @@ protected:
void unsetEdit(int ModNum) override;
void setEditViewer(Gui::View3DInventorViewer*, int ModNum) override;
void unsetEditViewer(Gui::View3DInventorViewer*) override;
- static void camSensCB(void* data, SoSensor*); // camera sensor callback
+ static void camSensCB(void* data, SoSensor*); // camera sensor callback
+ static void camSensDeleteCB(void* data, SoSensor*); // camera sensor callback
void onCameraChanged(SoCamera* cam);
//@}