Merge pull request #13906 from Rexbas/align-camera

Align camera to faces and edges
This commit is contained in:
Chris Hennes
2024-05-20 11:28:24 -05:00
committed by GitHub
11 changed files with 278 additions and 1 deletions

View File

@@ -209,6 +209,13 @@ void GeoFeature::setMaterialAppearance(const App::Material& material)
Q_UNUSED(material)
}
bool GeoFeature::getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const
{
Q_UNUSED(subname)
Q_UNUSED(direction)
return false;
}
#ifdef FC_USE_TNP_FIX
bool GeoFeature::hasMissingElement(const char* subname)
{

View File

@@ -141,6 +141,15 @@ public:
* appearance from an App::Material object.
*/
virtual void setMaterialAppearance(const App::Material& material);
/**
* @brief Virtual function to get the camera alignment direction
*
* Finds a direction to align the camera with.
*
* @return bool whether or not a direction is found.
*/
virtual bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname = nullptr) const;
#ifdef FC_USE_TNP_FIX
/** Search sub element using internal cached geometry
*

View File

@@ -4018,6 +4018,33 @@ bool StdRecallWorkingView::isActive()
return view && view->getViewer()->hasHomePosition();
}
//===========================================================================
// Std_AlignToSelection
//===========================================================================
DEF_STD_CMD_A(StdCmdAlignToSelection)
StdCmdAlignToSelection::StdCmdAlignToSelection()
: Command("Std_AlignToSelection")
{
sGroup = "View";
sMenuText = QT_TR_NOOP("Align to selection");
sToolTipText = QT_TR_NOOP("Align the view with the selection");
sWhatsThis = "Std_AlignToSelection";
sPixmap = "align-to-selection";
eType = Alter3DView;
}
void StdCmdAlignToSelection::activated(int iMsg)
{
Q_UNUSED(iMsg);
doCommand(Command::Gui,"Gui.SendMsgToActiveView(\"AlignToSelection\")");
}
bool StdCmdAlignToSelection::isActive()
{
return getGuiApplication()->sendHasMsgToActiveView("AlignToSelection");
}
//===========================================================================
// Instantiation
//===========================================================================
@@ -4049,6 +4076,7 @@ void CreateViewStdCommands()
rcCmdMgr.addCommand(new StdStoreWorkingView());
rcCmdMgr.addCommand(new StdRecallWorkingView());
rcCmdMgr.addCommand(new StdCmdViewGroup());
rcCmdMgr.addCommand(new StdCmdAlignToSelection());
rcCmdMgr.addCommand(new StdCmdViewExample1());
rcCmdMgr.addCommand(new StdCmdViewExample2());

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@@ -234,6 +234,7 @@
<file>colors.svg</file>
<file>px.svg</file>
<file>AddonManager.svg</file>
<file>align-to-selection.svg</file>
<file>Group.svg</file>
<file>Geofeaturegroup.svg</file>
<file>Geoassembly.svg</file>

View File

@@ -408,6 +408,10 @@ bool View3DInventor::onMsg(const char* pMsg, const char** ppReturn)
getGuiDocument()->saveCopy();
return true;
}
else if (strcmp("AlignToSelection", pMsg) == 0) {
_viewer->alignToSelection();
return true;
}
else if (strcmp("ZoomIn", pMsg) == 0) {
View3DInventorViewer* viewer = getViewer();
viewer->navigationStyle()->zoomIn();
@@ -511,6 +515,9 @@ bool View3DInventor::onHasMsg(const char* pMsg) const
else if(strncmp("Dump",pMsg,4) == 0) {
return true;
}
else if (strcmp("AlignToSelection", pMsg) == 0) {
return true;
}
if (strcmp("ZoomIn", pMsg) == 0) {
return true;
}

View File

@@ -3341,6 +3341,39 @@ void View3DInventorViewer::viewSelection()
}
}
void View3DInventorViewer::alignToSelection()
{
if (!getCamera()) {
return;
}
const auto selection = Selection().getSelection();
// Empty selection
if (selection.empty()) {
return;
}
// Too much selections
if (selection.size() > 1) {
return;
}
// Get the geo feature
App::GeoFeature* geoFeature = nullptr;
std::pair<std::string, std::string> elementName;
App::GeoFeature::resolveElement(selection[0].pObject, selection[0].SubName, elementName, false, App::GeoFeature::ElementNameType::Normal, nullptr, nullptr, &geoFeature);
if (!geoFeature) {
return;
}
Base::Vector3d direction;
if (geoFeature->getCameraAlignmentDirection(direction, selection[0].SubName)) {
const auto orientation = SbRotation(SbVec3f(0, 0, 1), Base::convertTo<SbVec3f>(direction));
setCameraOrientation(orientation);
}
}
/**
* @brief Decide if it should be possible to start any animation
*

View File

@@ -414,6 +414,8 @@ public:
*/
void viewSelection();
void alignToSelection();
void setGradientBackground(Background);
Background getGradientBackground() const;
void setGradientBackgroundColor(const SbColor& fromColor,

View File

@@ -804,7 +804,7 @@ ToolBarItem* StdWorkbench::setupToolBars() const
// View
auto view = new ToolBarItem( root );
view->setCommand("View");
*view << "Std_ViewFitAll" << "Std_ViewFitSelection" << "Std_ViewGroup"
*view << "Std_ViewFitAll" << "Std_ViewFitSelection" << "Std_ViewGroup" << "Std_AlignToSelection"
<< "Separator" << "Std_DrawStyle" << "Std_TreeViewActions"
<< "Separator" << "Std_MeasureDistance" << "Std_Measure";

View File

@@ -35,6 +35,7 @@
# include <BRepBuilderAPI_MakeVertex.hxx>
# include <BRepExtrema_DistShapeShape.hxx>
# include <BRepGProp.hxx>
# include <BRepGProp_Face.hxx>
# include <BRepIntCurveSurface_Inter.hxx>
# include <gce_MakeDir.hxx>
# include <gce_MakeLin.hxx>
@@ -68,6 +69,7 @@
#include <Base/Stream.h>
#include <Mod/Material/App/MaterialManager.h>
#include "Geometry.h"
#include "PartFeature.h"
#include "PartFeaturePy.h"
#include "PartPyCXX.h"
@@ -1655,6 +1657,44 @@ bool Feature::isElementMappingDisabled(App::PropertyContainer* container)
// return false;
}
bool Feature::getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const
{
const auto topoShape = getTopoShape(this, subname, true);
if (topoShape.isNull()) {
return false;
}
// Face normal
if (topoShape.isPlanar()) {
try {
const auto face = TopoDS::Face(topoShape.getShape());
gp_Pnt point;
gp_Vec vector;
BRepGProp_Face(face).Normal(0, 0, point, vector);
direction = Base::Vector3d(vector.X(), vector.Y(), vector.Z()).Normalize();
return true;
}
catch (Standard_TypeMismatch&) {
// Shape is not a face, do nothing
}
}
// Edge direction
const size_t edgeCount = topoShape.countSubShapes(TopAbs_EDGE);
if (edgeCount == 1 && topoShape.isLinearEdge()) {
if (const std::unique_ptr<Geometry> geometry = Geometry::fromShape(topoShape.getSubShape(TopAbs_EDGE, 1), true)) {
const std::unique_ptr<GeomLine> geomLine(static_cast<GeomCurve*>(geometry.get())->toLine());
if (geomLine) {
direction = geomLine->getDir().Normalize();
return true;
}
}
}
return GeoFeature::getCameraAlignmentDirection(direction, subname);
}
// ---------------------------------------------------------
PROPERTY_SOURCE(Part::FilletBase, Part::Feature)

View File

@@ -152,6 +152,8 @@ public:
create(const TopoShape& shape, const char* name = nullptr, App::Document* document = nullptr);
static bool isElementMappingDisabled(App::PropertyContainer *container);
bool getCameraAlignmentDirection(Base::Vector3d& direction, const char* subname) const override;
#ifdef FC_USE_TNP_FIX
const std::vector<std::string>& searchElementCache(const std::string &element,