PD: highlight current profile and sections of a loft when selecting a new profile/section

This commit is contained in:
wmayer
2021-12-13 15:01:08 +01:00
parent 506c40ab60
commit e6ea67bc1e
6 changed files with 249 additions and 46 deletions

View File

@@ -228,6 +228,8 @@ SET(PartDesignGuiModule_SRCS
CommandBody.cpp
EnumFlags.h
Resources/PartDesign.qrc
ReferenceHighlighter.cpp
ReferenceHighlighter.h
PreCompiled.cpp
PreCompiled.h
Utils.cpp

View File

@@ -0,0 +1,91 @@
/***************************************************************************
* Copyright (c) 2021 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#endif
#include <boost/algorithm/string/predicate.hpp>
#include "ReferenceHighlighter.h"
using namespace PartDesignGui;
ReferenceHighlighter::ReferenceHighlighter(const TopoDS_Shape& shape, const App::Color& color)
: lineColor(color)
, singleEdges(1.0f,0.0f,1.0f) // magenta
, allEdges(0.6f,0.0f,1.0f) // purple
{
TopExp::MapShapes(shape, TopAbs_EDGE, eMap);
TopExp::MapShapes(shape, TopAbs_FACE, fMap);
}
void ReferenceHighlighter::getEdgeColor(const std::string& element, std::vector<App::Color>& colors) const
{
int idx = std::stoi(element.substr(4)) - 1;
assert ( idx >= 0 );
std::size_t pos = std::size_t(idx);
if (pos < colors.size())
colors[pos] = singleEdges;
}
void ReferenceHighlighter::getEdgeColorsOfFace(const std::string& element, std::vector<App::Color>& colors) const
{
int idx = std::stoi(element.substr(4));
assert ( idx > 0 );
// get the edges of the faces
TopoDS_Shape face = fMap.FindKey(idx);
for (TopExp_Explorer xp(face, TopAbs_EDGE); xp.More(); xp.Next()) {
int edgeIndex = eMap.FindIndex(xp.Current());
// Edge found?
if (edgeIndex > 0) {
std::size_t pos = std::size_t(edgeIndex - 1);
if (pos < colors.size())
colors[pos] = singleEdges;
}
}
}
void ReferenceHighlighter::getEdgeColors(const std::vector<std::string>& elements,
std::vector<App::Color>& colors) const
{
colors.resize(eMap.Extent(), lineColor);
if (!elements.empty()) {
for (std::string e : elements) {
if (boost::starts_with(e, "Edge")) {
getEdgeColor(e, colors);
}
else if (boost::starts_with(e, "Face")) {
getEdgeColorsOfFace(e, colors);
}
}
}
else {
std::fill(colors.begin(), colors.end(), allEdges);
}
}

View File

@@ -0,0 +1,71 @@
/***************************************************************************
* Copyright (c) 2021 Werner Mayer <wmayer[at]users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library 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 Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
***************************************************************************/
#ifndef PARTGUI_REFERENCEHIGHLIGHTER_H
#define PARTGUI_REFERENCEHIGHLIGHTER_H
#include <App/Material.h>
#include <TopoDS_Shape.hxx>
#include <TopTools_IndexedMapOfShape.hxx>
#include <vector>
namespace PartDesignGui {
/*!
* \brief The ReferenceHighlighter class
* \author Werner Mayer
*/
class ReferenceHighlighter
{
public:
/*!
* \brief ReferenceHighlighter
* \param shape The input shape.
* \param color The standard edge color.
*/
ReferenceHighlighter(const TopoDS_Shape& shape, const App::Color& color);
/*!
* \brief getEdgeColors
* \param elements The sub-element names
* \param colors The size of the \a colors array is equal to the number of edges of the shape
*/
void getEdgeColors(const std::vector<std::string>& elements,
std::vector<App::Color>& colors) const;
private:
void getEdgeColor(const std::string& element, std::vector<App::Color>& colors) const;
void getEdgeColorsOfFace(const std::string& element, std::vector<App::Color>& colors) const;
private:
App::Color lineColor;
App::Color singleEdges;
App::Color allEdges;
TopTools_IndexedMapOfShape eMap;
TopTools_IndexedMapOfShape fMap;
};
} // namespace PartDesignGui
#endif // PARTGUI_REFERENCEHIGHLIGHTER_H

View File

@@ -172,7 +172,6 @@ void TaskLoftParameters::onSelectionChanged(const Gui::SelectionChanges& msg)
}
clearButtons();
//static_cast<ViewProviderLoft*>(vp)->highlightReferences(false, true);
recomputeFeature();
}
@@ -202,6 +201,7 @@ bool TaskLoftParameters::referenceSelected(const Gui::SelectionChanges& msg) con
App::DocumentObject* obj = loft->getDocument()->getObject(msg.pObjectName);
if (selectionMode == refProfile) {
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Profile, false);
loft->Profile.setValue(obj, {msg.pSubName});
return true;
}
@@ -262,7 +262,6 @@ void TaskLoftParameters::onDeleteSection()
// `setValues(ref)` cleanly ensures subnames are preserved.
loft->Sections.removeValue(obj);
//static_cast<ViewProviderLoft*>(vp)->highlightReferences(false, true);
recomputeFeature();
updateUI();
}
@@ -328,7 +327,12 @@ void TaskLoftParameters::onProfileButton(bool checked)
Gui::Selection().clearSelection();
selectionMode = refProfile;
this->blockSelection(false);
//static_cast<ViewProviderLoft*>(vp)->highlightReferences(true, true);
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, true);
}
else {
Gui::Selection().clearSelection();
selectionMode = none;
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, false);
}
}
@@ -339,7 +343,12 @@ void TaskLoftParameters::onRefButtonAdd(bool checked)
Gui::Selection().clearSelection();
selectionMode = refAdd;
this->blockSelection(false);
//static_cast<ViewProviderLoft*>(vp)->highlightReferences(true, true);
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, true);
}
else {
Gui::Selection().clearSelection();
selectionMode = none;
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, false);
}
}
@@ -350,7 +359,12 @@ void TaskLoftParameters::onRefButtonRemove(bool checked)
Gui::Selection().clearSelection();
selectionMode = refRemove;
this->blockSelection(false);
//static_cast<ViewProviderLoft*>(vp)->highlightReferences(true, true);
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, true);
}
else {
Gui::Selection().clearSelection();
selectionMode = none;
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, false);
}
}
@@ -379,6 +393,7 @@ bool TaskDlgLoftParameters::accept()
{
// TODO Fill this with commands (2015-09-11, Fat-Zer)
PartDesign::Loft* pcLoft = static_cast<PartDesign::Loft*>(vp->getObject());
static_cast<ViewProviderLoft*>(vp)->highlightReferences(ViewProviderLoft::Both, false);
for (App::DocumentObject* obj : pcLoft->Sections.getValues()) {
FCMD_OBJ_HIDE(obj);

View File

@@ -26,14 +26,12 @@
#ifndef _PreComp_
# include <QMessageBox>
# include <QMenu>
# include <TopExp.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
#endif
#include "Utils.h"
#include "ViewProviderLoft.h"
//#include "TaskLoftParameters.h"
#include "TaskLoftParameters.h"
#include "ReferenceHighlighter.h"
#include <Mod/PartDesign/App/Body.h>
#include <Mod/PartDesign/App/FeatureLoft.h>
#include <Mod/Sketcher/App/SketchObject.h>
@@ -115,47 +113,63 @@ bool ViewProviderLoft::onDelete(const std::vector<std::string> & /*s*/)
return true;
}
void ViewProviderLoft::highlightReferences(const bool /*on*/, bool /*auxiliary*/)
{/*
void ViewProviderLoft::highlightProfile(bool on)
{
PartDesign::Loft* pcLoft = static_cast<PartDesign::Loft*>(getObject());
Part::Feature* base;
if(!auxiliary)
base = static_cast<Part::Feature*>(pcLoft->Spine.getValue());
else
base = static_cast<Part::Feature*>(pcLoft->AuxillerySpine.getValue());
highlightReferences(dynamic_cast<Part::Feature*>(pcLoft->Profile.getValue()),
pcLoft->Profile.getSubValues(), on);
}
if (base == NULL) return;
void ViewProviderLoft::highlightSection(bool on)
{
PartDesign::Loft* pcLoft = static_cast<PartDesign::Loft*>(getObject());
auto sections = pcLoft->Sections.getSubListValues();
for (auto it : sections) {
if (it.second.size() == 1 && it.second[0].empty())
it.second.clear();
highlightReferences(dynamic_cast<Part::Feature*>(it.first), it.second, on);
}
}
void ViewProviderLoft::highlightReferences(ViewProviderLoft::Reference mode, bool on)
{
switch (mode) {
case Profile:
highlightProfile(on);
break;
case Section:
highlightSection(on);
break;
case Both:
highlightProfile(on);
highlightSection(on);
break;
default:
break;
}
}
void ViewProviderLoft::highlightReferences(Part::Feature* base, const std::vector<std::string>& elements, bool on)
{
PartGui::ViewProviderPart* svp = dynamic_cast<PartGui::ViewProviderPart*>(
Gui::Application::Instance->getViewProvider(base));
if (svp == NULL) return;
if (svp == nullptr)
return;
std::vector<std::string> edges;
if(!auxiliary)
edges = pcLoft->Spine.getSubValuesStartsWith("Edge");
else
edges = pcLoft->AuxillerySpine.getSubValuesStartsWith("Edge");
std::vector<App::Color>& edgeColors = originalLineColors[base->getID()];
if (on) {
if (!edges.empty() && originalLineColors.empty()) {
TopTools_IndexedMapOfShape eMap;
TopExp::MapShapes(base->Shape.getValue(), TopAbs_EDGE, eMap);
originalLineColors = svp->LineColorArray.getValues();
std::vector<App::Color> colors = originalLineColors;
colors.resize(eMap.Extent(), svp->LineColor.getValue());
edgeColors = svp->LineColorArray.getValues();
std::vector<App::Color> colors = edgeColors;
for (std::string e : edges) {
int idx = atoi(e.substr(4).c_str()) - 1;
if (idx < colors.size())
colors[idx] = App::Color(1.0,0.0,1.0); // magenta
}
svp->LineColorArray.setValues(colors);
}
} else {
if (!edges.empty() && !originalLineColors.empty()) {
svp->LineColorArray.setValues(originalLineColors);
originalLineColors.clear();
}
}*/
ReferenceHighlighter highlighter(base->Shape.getValue(), svp->LineColor.getValue());
highlighter.getEdgeColors(elements, colors);
svp->LineColorArray.setValues(colors);
}
else if (!edgeColors.empty()) {
svp->LineColorArray.setValues(edgeColors);
edgeColors.clear();
}
}
QIcon ViewProviderLoft::getIcon(void) const {

View File

@@ -33,6 +33,12 @@ class PartDesignGuiExport ViewProviderLoft : public ViewProviderAddSub
PROPERTY_HEADER(PartDesignGui::ViewProviderLoft);
public:
enum Reference {
Profile,
Section,
Both
};
/// constructor
ViewProviderLoft();
/// destructor
@@ -43,17 +49,21 @@ public:
void setupContextMenu(QMenu*, QObject*, const char*);
virtual bool onDelete(const std::vector<std::string> &);
void highlightReferences(const bool on, bool auxiliary);
void highlightProfile(bool on);
void highlightSection(bool on);
void highlightReferences(Reference mode, bool on);
protected:
virtual QIcon getIcon(void) const;
virtual bool setEdit(int ModNum);
virtual void unsetEdit(int ModNum);
virtual TaskDlgFeatureParameters* getEditDialog();
virtual QIcon getIcon(void) const;
private:
std::vector<App::Color> originalLineColors;
void highlightReferences(Part::Feature*, const std::vector<std::string>&, bool);
private:
std::map<long, std::vector<App::Color>> originalLineColors;
};