data()->addAttribute(FILE_PATH_ID(), ModelAPI_AttributeString::typeId());
data()->addAttribute(FILE_FORMAT_ID(), ModelAPI_AttributeString::typeId());
- data()->addAttribute(GEOMETRIC_DUMP_ID(), ModelAPI_AttributeBoolean::typeId());
- boolean(GEOMETRIC_DUMP_ID())->setValue(false);
+ data()->addAttribute(SELECTION_TYPE_ID(), ModelAPI_AttributeString::typeId());
+ //string(SELECTION_TYPE_ID())->setValue(TOPOLOGICAL_NAMING_DUMP_ID()); // default value
}
void ExchangePlugin_Dump::execute()
ModelHighAPI_Dumper* aDumper = ModelHighAPI_Dumper::getInstance();
aDumper->clear();
- aDumper->setSelectionByGeometry(boolean(GEOMETRIC_DUMP_ID())->value());
+ aDumper->setSelectionByGeometry(string(SELECTION_TYPE_ID())->value() == GEOMETRIC_DUMP_ID());
+ aDumper->setSelectionWeakNaming(string(SELECTION_TYPE_ID())->value() == WEAK_NAMING_DUMP_ID());
DocumentPtr aDoc = ModelAPI_Session::get()->moduleDocument();
static const std::string MY_FILE_FORMAT_ID("file_format");
return MY_FILE_FORMAT_ID;
}
- /// attribute name of flag dumping by geometric selection (not by naming)
+ /// attribute name of selection type string (GUI radio button) of dumping by topological naming
+ inline static const std::string& SELECTION_TYPE_ID()
+ {
+ static const std::string MY_SELECTION_TYPE_ID("selection_type");
+ return MY_SELECTION_TYPE_ID;
+ }
+
+ /// string identifier of dumping by topological naming
+ inline static const std::string& TOPOLOGICAL_NAMING_DUMP_ID()
+ {
+ static const std::string MY_TOOPNAMING_DUMP_ID("topological_naming");
+ return MY_TOOPNAMING_DUMP_ID;
+ }
+ /// string identifier of dumping by geometric selection
inline static const std::string& GEOMETRIC_DUMP_ID()
{
- static const std::string MY_GEOM_DUMP_ID("geometric_dump");
+ static const std::string MY_GEOM_DUMP_ID("geometric_selection");
return MY_GEOM_DUMP_ID;
}
+ /// string identifier of dumping by using weak naming identifiers of selection
+ inline static const std::string& WEAK_NAMING_DUMP_ID()
+ {
+ static const std::string MY_WEAK_NAMING_DUMP_ID("weak_naming");
+ return MY_WEAK_NAMING_DUMP_ID;
+ }
+
/// Default constructor
EXCHANGEPLUGIN_EXPORT ExchangePlugin_Dump();
/// Default destructor
<validator id="ExchangePlugin_ExportFormat"
parameters="py:Python" />
</export_file_selector>
- <boolvalue id="geometric_dump" label="By geometric selection"/>
+ <radiobox id="selection_type">
+ <radio id="topological_naming"
+ title="Topological naming selection"
+ tooltip="To use standard topological naming selection identifier, used for parametric model"/>
+ <radio id="geometric_selection"
+ title="Geometric selection"
+ tooltip="To use geometrical point coordinates to identify selected shapes"/>
+ <radio id="weak_naming"
+ title="Weak naming selection"
+ tooltip="To use geometrical order for identification of selected shapes"/>
+ </radiobox>
</feature>
</group>
</workbench>
GeomAlgoAPI_SortListOfShapes.h
GeomAlgoAPI_Filling.h
GeomAlgoAPI_CurveBuilder.h
+ GeomAlgoAPI_NExplode.h
)
SET(PROJECT_SOURCES
GeomAlgoAPI_SortListOfShapes.cpp
GeomAlgoAPI_Filling.cpp
GeomAlgoAPI_CurveBuilder.cpp
+ GeomAlgoAPI_NExplode.cpp
)
SET(PROJECT_LIBRARIES
--- /dev/null
+// Copyright (C) 2017 CEA/DEN, EDF R&D
+//
+// This library 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.
+//
+// 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#include "GeomAlgoAPI_NExplode.h"
+
+#include <TopoDS_Shape.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <GProp_GProps.hxx>
+#include <BRepGProp.hxx>
+#include <NCollection_DataMap.hxx>
+#include <Precision.hxx>
+#include <Bnd_Box.hxx>
+#include <BRepBndLib.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopTools_MapOfShape.hxx>
+
+#include <vector>
+#include <algorithm>
+
+static std::pair<double, double> ShapeToDouble (const TopoDS_Shape& S)
+{
+ // Computing of CentreOfMass
+ gp_Pnt GPoint;
+ double Len;
+
+ if (S.ShapeType() == TopAbs_VERTEX) {
+ GPoint = BRep_Tool::Pnt(TopoDS::Vertex(S));
+ Len = (double)S.Orientation();
+ }
+ else {
+ GProp_GProps GPr;
+ if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) {
+ BRepGProp::LinearProperties(S, GPr);
+ }
+ else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) {
+ BRepGProp::SurfaceProperties(S, GPr);
+ }
+ else {
+ BRepGProp::VolumeProperties(S, GPr);
+ }
+ GPoint = GPr.CentreOfMass();
+ Len = GPr.Mass();
+ }
+
+ double dMidXYZ = GPoint.X() * 999.0 + GPoint.Y() * 99.0 + GPoint.Z() * 0.9;
+ return std::make_pair(dMidXYZ, Len);
+}
+
+/*!
+* \brief Sort shapes in the list by their coordinates.
+*/
+struct CompareShapes : public std::binary_function<TopoDS_Shape, TopoDS_Shape, bool>
+{
+ typedef NCollection_DataMap<TopoDS_Shape, std::pair<double, double> > DataMapOfShapeDouble;
+
+ CompareShapes(DataMapOfShapeDouble* theCashMap) : myMap(theCashMap) {}
+
+ bool operator() (const TopoDS_Shape& lhs, const TopoDS_Shape& rhs);
+
+ DataMapOfShapeDouble* myMap;
+};
+
+bool CompareShapes::operator() (const TopoDS_Shape& theShape1,
+ const TopoDS_Shape& theShape2)
+{
+ if (!myMap->IsBound(theShape1)) {
+ myMap->Bind(theShape1, ShapeToDouble(theShape1));
+ }
+
+ if (!myMap->IsBound(theShape2)) {
+ myMap->Bind(theShape2, ShapeToDouble(theShape2));
+ }
+
+ std::pair<double, double> val1 = myMap->Find(theShape1);
+ std::pair<double, double> val2 = myMap->Find(theShape2);
+
+ double tol = Precision::Confusion();
+ bool exchange = Standard_False;
+
+ double dMidXYZ = val1.first - val2.first;
+ if (dMidXYZ >= tol) {
+ exchange = Standard_True;
+ }
+ else if (Abs(dMidXYZ) < tol) {
+ double dLength = val1.second - val2.second;
+ if (dLength >= tol) {
+ exchange = Standard_True;
+ }
+ else if (Abs(dLength) < tol && theShape1.ShapeType() <= TopAbs_FACE) {
+ // equal values possible on shapes such as two halves of a sphere and
+ // a membrane inside the sphere
+ Bnd_Box box1,box2;
+ BRepBndLib::Add(theShape1, box1);
+ if (!box1.IsVoid()) {
+ BRepBndLib::Add(theShape2, box2);
+ Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent();
+ if (dSquareExtent >= tol) {
+ exchange = Standard_True;
+ }
+ else if (Abs(dSquareExtent) < tol) {
+ Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2;
+ box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ val1 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
+ box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ val2 = (aXmin+aXmax)*999.0 + (aYmin+aYmax)*99.0 + (aZmin+aZmax)*0.9;
+ if ((val1 - val2) >= tol) {
+ exchange = Standard_True;
+ }
+ }
+ }
+ } else // compare adresses if shapes are geometrically equal
+ return theShape1.TShape().get() > theShape2.TShape().get();
+ }
+
+ //return val1 < val2;
+ return !exchange;
+}
+
+GeomAlgoAPI_NExplode::GeomAlgoAPI_NExplode(
+ const GeomShapePtr theContext, const GeomAPI_Shape::ShapeType theShapeType)
+{
+ std::vector<TopoDS_Shape> aShapesVec;
+
+ const TopoDS_Shape& aContext = theContext->impl<TopoDS_Shape>();
+ TopExp_Explorer anExp(aContext, (TopAbs_ShapeEnum)theShapeType);
+ TopTools_MapOfShape aMapShape;
+ for(; anExp.More(); anExp.Next()) {
+ if (aMapShape.Add(anExp.Current()))
+ aShapesVec.push_back(anExp.Current());
+ }
+
+ CompareShapes::DataMapOfShapeDouble aCash;
+ CompareShapes shComp(&aCash);
+ std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
+
+ std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
+ for (; anIter != aShapesVec.end(); ++anIter) {
+ GeomShapePtr aShapePtr(new GeomAPI_Shape);
+ aShapePtr->setImpl<TopoDS_Shape>(new TopoDS_Shape(*anIter));
+ mySorted.push_back(aShapePtr);
+ }
+}
+
+int GeomAlgoAPI_NExplode::index(const GeomShapePtr theSubShape)
+{
+ ListOfShape::iterator anIter = mySorted.begin();
+ for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) {
+ if ((*anIter)->isSame(theSubShape))
+ return anIndex;
+ }
+ return 0; // not found
+}
+
+GeomShapePtr GeomAlgoAPI_NExplode::shape(const int theIndex)
+{
+ ListOfShape::iterator anIter = mySorted.begin();
+ for(int anIndex = 1; anIter != mySorted.end(); anIter++, anIndex++) {
+ if (anIndex == theIndex)
+ return *anIter;
+ }
+ return GeomShapePtr(); // not found
+}
--- /dev/null
+// Copyright (C) 2017 CEA/DEN, EDF R&D
+//
+// This library 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.
+//
+// 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
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or
+// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+//
+
+#ifndef GeomAlgoAPI_NExplode_H_
+#define GeomAlgoAPI_NExplode_H_
+
+#include "GeomAlgoAPI.h"
+
+#include <GeomAPI_Shape.h>
+
+/// \class GeomAlgoAPI_NExplode
+/// \ingroup DataAlgo
+/// \brief Sort shapes by their centers of mass, using formula X*999 + Y*99 + Z*0.9.
+/// Algorithm is copied from GEOM module, which uses nexplode Draw command from OCCT.
+/// Used for getting index of sub0shape in WeakNaming algorithm.
+class GeomAlgoAPI_NExplode
+{
+ public:
+ /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
+ GEOMALGOAPI_EXPORT GeomAlgoAPI_NExplode(
+ const GeomShapePtr theContext, const GeomAPI_Shape::ShapeType theShapeType);
+
+ /// Returns an index (started from one) of sub-shape in the sorted list. Returns 0 if not found.
+ GEOMALGOAPI_EXPORT int index(const GeomShapePtr theSubShape);
+ /// Returns a shape by an index (started from one). Returns null if not found.
+ GEOMALGOAPI_EXPORT GeomShapePtr shape(const int theIndex);
+
+protected:
+ ListOfShape mySorted;
+};
+
+#endif
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Vertex.h>
#include <GeomAlgoAPI_CompoundBuilder.h>
+#include <GeomAlgoAPI_NExplode.h>
#include <TNaming_Selector.hxx>
#include <TNaming_NamedShape.hxx>
reset();
}
+void Model_AttributeSelection::selectSubShape(const std::string& theType,
+ const std::string& theContextName, const int theIndex)
+{
+ // selection of context by name
+ //std::string aNamingContextName = theContextName + "/";
+ //selectSubShape(theType, aNamingContextName);
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ if (aDoc.get()) {
+ bool aUnique = true;
+ std::string aContextName = theContextName;
+ std::string anEmptySub = "";
+ ResultPtr aContext = aDoc->findByName(aContextName, anEmptySub, aUnique);
+ //ResultPtr aContext = context();
+ if (aContext.get()) {
+ GeomShapePtr aContShape = aContext->shape();
+ if (aContShape.get()) {
+ GeomAlgoAPI_NExplode aNExp(aContShape, GeomAPI_Shape::shapeTypeByStr(theType));
+ GeomShapePtr aValue = aNExp.shape(theIndex);
+ if (aValue.get())
+ setValue(aContext, aValue);
+ }
+ }
+ }
+}
+
int Model_AttributeSelection::Id()
{
int anID = 0;
/// Selects sub-shape by its inner point
MODEL_EXPORT virtual void selectSubShape(const std::string& theType,
const std::shared_ptr<GeomAPI_Pnt>& thePoint);
+ /// Selects sub-shape by weak naming index
+ MODEL_EXPORT virtual void selectSubShape(const std::string& theType,
+ const std::string& theContextName, const int theIndex);
/// Returns true if attribute was initialized by some value
MODEL_EXPORT virtual bool isInitialized();
owner()->data()->sendAttributeUpdated(this);
}
+void Model_AttributeSelectionList::append(const std::string& theType,
+ const std::string& theContextName, const int theIndex)
+{
+ int aNewTag = mySize->Get() + 1;
+ TDF_Label aNewLab = mySize->Label().FindChild(aNewTag);
+
+ std::shared_ptr<Model_AttributeSelection> aNewAttr =
+ std::shared_ptr<Model_AttributeSelection>(new Model_AttributeSelection(aNewLab));
+ if (owner()) {
+ aNewAttr->setObject(owner());
+ aNewAttr->setParent(this);
+ }
+ aNewAttr->setID(id());
+ mySize->Set(aNewTag);
+ aNewAttr->selectSubShape(theType, theContextName, theIndex);
+ owner()->data()->sendAttributeUpdated(this);
+}
+
void Model_AttributeSelectionList::removeTemporaryValues()
{
if (myTmpAttr.get()) {
MODEL_EXPORT virtual void append(const std::shared_ptr<GeomAPI_Pnt>& thePoint,
const std::string& theType);
+ /// Adds the new reference to the end of the list by weak naming index
+ MODEL_EXPORT virtual void append(const std::string& theType, const std::string& theContextName,
+ const int theIndex);
+
/// Reset temporary stored values
virtual void removeTemporaryValues();
virtual void selectSubShape(const std::string& theType,
const std::shared_ptr<GeomAPI_Pnt>& thePoint) = 0;
+ /// Selects sub-shape by weak naming index
+ virtual void selectSubShape(const std::string& theType,
+ const std::string& theContextName, const int theIndex) = 0;
+
/// Returns true if recompute of selection become impossible
virtual bool isInvalid() = 0;
virtual void append(const std::shared_ptr<GeomAPI_Pnt>& thePoint,
const std::string& theType) = 0;
+ /// Adds the new reference to the end of the list by weak naming index
+ virtual void append(const std::string& theType, const std::string& theContextName,
+ const int theIndex) = 0;
+
/// Reset temporary stored values
virtual void removeTemporaryValues() = 0;
#include <GeomAPI_Pnt.h>
#include <GeomAPI_Dir.h>
#include <GeomAPI_ShapeExplorer.h>
+#include <GeomAlgoAPI_NExplode.h>
#include <GeomDataAPI_Dir.h>
#include <GeomDataAPI_Point.h>
}
myDumpBuffer << "\"" << aShape->shapeTypeStr();
+ bool aStandardDump = true;
if (isDumpByGeom) {
// check the selected item is a ResultPart;
// in this case it is necessary to get shape with full transformation
myDumpBuffer << anIndex << "\", ";
*this << aMiddlePoint;
+ aStandardDump = false;
+ } if (myWeakNamingSelection && aShape.get() && theAttrSelect->context().get() &&
+ aShape != theAttrSelect->context()->shape()) { // weak naming for local selection only
+ GeomAlgoAPI_NExplode aNExplode(theAttrSelect->context()->shape(), aShape->shapeType());
+ int anIndex = aNExplode.index(aShape);
+ if (anIndex != 0) { // found a week-naming index, so, export it
+ myDumpBuffer<<"\", \""<<theAttrSelect->context()->data()->name()<<"\", "<<anIndex;
+ aStandardDump = false;
+ }
}
- else
+ if (aStandardDump)
myDumpBuffer << "\", \"" << theAttrSelect->namingName() << "\"";
myDumpBuffer << ")";
return *this;
void setSelectionByGeometry(bool theDumpByGeom = true)
{ myGeometricalSelection = theDumpByGeom; }
+ /// Set/unset flag to dump selection attributes by weak naming
+ void setSelectionWeakNaming(bool theDumpByWeakNaming = true)
+ { myWeakNamingSelection = theDumpByWeakNaming; }
+
/// Dump given document into the file
/// \return \c true, if succeed
MODELHIGHAPI_EXPORT
bool myDumpPostponedInProgress; ///< processing postponed is in progress
bool myGeometricalSelection; ///< dump selection not by naming, but by coordinates of inner point
+ bool myWeakNamingSelection; ///< dump selection by weak naming
protected:
/// list of entities, used by other features but not dumped yet
{
}
+ModelHighAPI_Selection::ModelHighAPI_Selection(const std::string& theType,
+ const std::string& theContextName, const int theIndex)
+ : myVariantType(VT_WeakNamingPair)
+ , myWeakNamingPair(theType, std::pair<std::string, int>(theContextName, theIndex))
+{
+}
+
+
ModelHighAPI_Selection::~ModelHighAPI_Selection()
{
}
case VT_TypeInnerPointPair:
theAttribute->selectSubShape(myTypeInnerPointPair.first, myTypeInnerPointPair.second);
return;
+ case VT_WeakNamingPair:
+ theAttribute->selectSubShape(
+ myWeakNamingPair.first, myWeakNamingPair.second.first, myWeakNamingPair.second.second);
+ break;
}
if (theAttribute->isInvalid()) {
// Note: the reverse order (first - type, second - selected point)
theAttribute->append(myTypeInnerPointPair.second, myTypeInnerPointPair.first);
return;
+ case VT_WeakNamingPair:
+ // Note: the reverse order (first - type, second - selected point)
+ theAttribute->append(
+ myWeakNamingPair.first, myWeakNamingPair.second.first, myWeakNamingPair.second.second);
+ return;
}
}
ResultSubShapePair;
typedef std::pair<std::string, std::string> TypeSubShapeNamePair;
typedef std::pair<std::string, std::shared_ptr<GeomAPI_Pnt> > TypeInnerPointPair;
+typedef std::pair<std::string, std::pair<std::string, int> > TypeWeakNamingPair;
//--------------------------------------------------------------------------------------
/**\class ModelHighAPI_Selection
* \ingroup CPPHighAPI
VT_Empty,
VT_ResultSubShapePair,
VT_TypeSubShapeNamePair,
- VT_TypeInnerPointPair
+ VT_TypeInnerPointPair,
+ VT_WeakNamingPair
};
public:
ModelHighAPI_Selection(const std::string& theType,
const std::shared_ptr<GeomAPI_Pnt>& theSubShapeInnerPoint);
+
+ /// Constructor for sub-shape by weak naming identifier
+ MODELHIGHAPI_EXPORT
+ ModelHighAPI_Selection(const std::string& theType,
+ const std::string& theContextName, const int theIndex);
+
/// Destructor
MODELHIGHAPI_EXPORT
virtual ~ModelHighAPI_Selection();
ResultSubShapePair myResultSubShapePair;
TypeSubShapeNamePair myTypeSubShapeNamePair;
TypeInnerPointPair myTypeInnerPointPair;
+ TypeWeakNamingPair myWeakNamingPair;
};
//--------------------------------------------------------------------------------------