Skip to content

Commit

Permalink
Part: make Fusion and Common able to fuse arrays
Browse files Browse the repository at this point in the history
If Fusion or Common features get only one argument, and the shape is a
compound, the children of the compound are treated as list of arguments.
  • Loading branch information
DeepSOIC authored and wwmayer committed Aug 7, 2016
1 parent 6135ec5 commit 433bd37
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 6 deletions.
42 changes: 42 additions & 0 deletions src/Mod/Part/App/FeaturePartCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
# include <BRepAlgoAPI_Common.hxx>
# include <BRepCheck_Analyzer.hxx>
# include <Standard_Failure.hxx>
# include <TopoDS_Iterator.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
# include <TopExp.hxx>
#endif


Expand Down Expand Up @@ -84,6 +87,23 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void)
}
}

bool argumentsAreInCompound = false;
TopoDS_Shape compoundOfArguments;

//if only one source shape, and it is a compound - fuse children of the compound
if (s.size() == 1){
compoundOfArguments = s[0];
if (compoundOfArguments.ShapeType() == TopAbs_COMPOUND){
s.clear();
TopoDS_Iterator it(compoundOfArguments);
for (; it.More(); it.Next()) {
const TopoDS_Shape& aChild = it.Value();
s.push_back(aChild);
}
argumentsAreInCompound = true;
}
}

if (s.size() >= 2) {
try {
std::vector<ShapeHistory> history;
Expand Down Expand Up @@ -129,6 +149,28 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void)
}

this->Shape.setValue(resShape);

if (argumentsAreInCompound){
//combine histories of every child of source compound into one
ShapeHistory overallHist;
TopTools_IndexedMapOfShape facesOfCompound;
TopAbs_ShapeEnum type = TopAbs_FACE;
TopExp::MapShapes(compoundOfArguments, type, facesOfCompound);
for (int iChild = 0; iChild < history.size(); iChild++){ //loop over children of source compound
//for each face of a child, find the inex of the face in compound, and assign the corresponding right-hand-size of the history
TopTools_IndexedMapOfShape facesOfChild;
TopExp::MapShapes(s[iChild], type, facesOfChild);
for(std::pair<const int,ShapeHistory::List> &histitem: history[iChild].shapeMap){ //loop over elements of history - that is - over faces of the child of source compound
int iFaceInChild = histitem.first;
ShapeHistory::List &iFacesInResult = histitem.second;
TopoDS_Shape srcFace = facesOfChild(iFaceInChild + 1); //+1 to convert our 0-based to OCC 1-bsed conventions
int iFaceInCompound = facesOfCompound.FindIndex(srcFace)-1;
overallHist.shapeMap[iFaceInCompound] = iFacesInResult; //this may overwrite existing info if the same face is used in several children of compound. This shouldn't be a problem, because the histories should match anyway...
}
}
history.clear();
history.push_back(overallHist);
}
this->History.setValues(history);
}
catch (Standard_Failure) {
Expand Down
43 changes: 43 additions & 0 deletions src/Mod/Part/App/FeaturePartFuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
# include <BRepAlgoAPI_Fuse.hxx>
# include <BRepCheck_Analyzer.hxx>
# include <Standard_Failure.hxx>
# include <TopoDS_Iterator.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
# include <TopExp.hxx>
#endif


Expand Down Expand Up @@ -83,6 +86,23 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void)
}
}

bool argumentsAreInCompound = false;
TopoDS_Shape compoundOfArguments;

//if only one source shape, and it is a compound - fuse children of the compound
if (s.size() == 1){
compoundOfArguments = s[0];
if (compoundOfArguments.ShapeType() == TopAbs_COMPOUND){
s.clear();
TopoDS_Iterator it(compoundOfArguments);
for (; it.More(); it.Next()) {
const TopoDS_Shape& aChild = it.Value();
s.push_back(aChild);
}
argumentsAreInCompound = true;
}
}

if (s.size() >= 2) {
try {
std::vector<ShapeHistory> history;
Expand Down Expand Up @@ -153,6 +173,29 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void)
}

this->Shape.setValue(resShape);


if (argumentsAreInCompound){
//combine histories of every child of source compound into one
ShapeHistory overallHist;
TopTools_IndexedMapOfShape facesOfCompound;
TopAbs_ShapeEnum type = TopAbs_FACE;
TopExp::MapShapes(compoundOfArguments, type, facesOfCompound);
for (int iChild = 0; iChild < history.size(); iChild++){ //loop over children of source compound
//for each face of a child, find the inex of the face in compound, and assign the corresponding right-hand-size of the history
TopTools_IndexedMapOfShape facesOfChild;
TopExp::MapShapes(s[iChild], type, facesOfChild);
for(std::pair<const int,ShapeHistory::List> &histitem: history[iChild].shapeMap){ //loop over elements of history - that is - over faces of the child of source compound
int iFaceInChild = histitem.first;
ShapeHistory::List &iFacesInResult = histitem.second;
TopoDS_Shape srcFace = facesOfChild(iFaceInChild + 1); //+1 to convert our 0-based to OCC 1-bsed conventions
int iFaceInCompound = facesOfCompound.FindIndex(srcFace)-1;
overallHist.shapeMap[iFaceInCompound] = iFacesInResult; //this may overwrite existing info if the same face is used in several children of compound. This shouldn't be a problem, because the histories should match anyway...
}
}
history.clear();
history.push_back(overallHist);
}
this->History.setValues(history);
}
catch (Standard_Failure) {
Expand Down
4 changes: 4 additions & 0 deletions src/Mod/Part/App/PropertyTopoShape.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ class PartExport PropertyPartShape : public App::PropertyComplexGeoData
};

struct PartExport ShapeHistory {
/**
* @brief MapList: key is index of subshape (of type 'type') in source
* shape. Value is list of indexes of subshapes in result shape.
*/
typedef std::map<int, std::vector<int> > MapList;
typedef std::vector<int> List;

Expand Down
51 changes: 45 additions & 6 deletions src/Mod/Part/Gui/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
# include <TopExp_Explorer.hxx>
# include <Inventor/events/SoMouseButtonEvent.h>
# include <Standard_Version.hxx>
# include <TopoDS_TCompound.hxx>
#endif

#include <Base/Console.h>
Expand Down Expand Up @@ -350,9 +351,28 @@ CmdPartCommon::CmdPartCommon()
void CmdPartCommon::activated(int iMsg)
{
std::vector<Gui::SelectionObject> Sel = getSelection().getSelectionEx(0, Part::Feature::getClassTypeId());
if (Sel.size() < 2) {

//test if selected object is a compound, and if it is, look how many children it has...
int numShapes = 0;
if (Sel.size() == 1){
numShapes = 1; //to be updated later in code, if
Gui::SelectionObject selobj = Sel[0];
if (selobj.getObject()->isDerivedFrom(Part::Feature::getClassTypeId())){
TopoDS_Shape sh = static_cast<Part::Feature*>(selobj.getObject())->Shape.getValue();
if (sh.ShapeType() == TopAbs_COMPOUND) {
numShapes = 0;
TopoDS_Iterator it(sh);
for (; it.More(); it.Next()) {
++numShapes;
}
}
}
} else {
numShapes = Sel.size();
}
if (numShapes < 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select two shapes or more, please."));
QObject::tr("Select two shapes or more, please. Or, select one compound containing two or more shapes to compute common between."));
return;
}

Expand Down Expand Up @@ -409,7 +429,7 @@ void CmdPartCommon::activated(int iMsg)

bool CmdPartCommon::isActive(void)
{
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=2;
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=1;
}

//===========================================================================
Expand All @@ -432,9 +452,28 @@ CmdPartFuse::CmdPartFuse()
void CmdPartFuse::activated(int iMsg)
{
std::vector<Gui::SelectionObject> Sel = getSelection().getSelectionEx(0, Part::Feature::getClassTypeId());
if (Sel.size() < 2) {

//test if selected object is a compound, and if it is, look how many children it has...
int numShapes = 0;
if (Sel.size() == 1){
numShapes = 1; //to be updated later in code
Gui::SelectionObject selobj = Sel[0];
if (selobj.getObject()->isDerivedFrom(Part::Feature::getClassTypeId())){
TopoDS_Shape sh = static_cast<Part::Feature*>(selobj.getObject())->Shape.getValue();
if (sh.ShapeType() == TopAbs_COMPOUND) {
numShapes = 0;
TopoDS_Iterator it(sh);
for (; it.More(); it.Next()) {
++numShapes;
}
}
}
} else {
numShapes = Sel.size();
}
if (numShapes < 2) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
QObject::tr("Select two shapes or more, please."));
QObject::tr("Select two shapes or more, please. Or, select one compound containing two or more shapes to be fused."));
return;
}

Expand Down Expand Up @@ -491,7 +530,7 @@ void CmdPartFuse::activated(int iMsg)

bool CmdPartFuse::isActive(void)
{
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=2;
return getSelection().countObjectsOfType(Part::Feature::getClassTypeId())>=1;
}

//===========================================================================
Expand Down

0 comments on commit 433bd37

Please sign in to comment.