#include <ModelAPI_CompositeFeature.h>
#include <GeomAPI_Shape.h>
#include <GeomAPI_PlanarEdges.h>
-#include <GeomAlgoAPI_SketchBuilder.h>
#include <Events_Error.h>
#include <TNaming_Selector.hxx>
static const int kSTART_VERTEX_DELTA = 1000000;
// identifier that there is simple reference: selection equals to context
Standard_GUID kSIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb29");
+Standard_GUID kCONSTUCTION_SIMPLE_REF_ID("635eacb2-a1d6-4dec-8348-471fae17cb28");
// on this label is stored:
// TNaming_NamedShape - selected shape
const std::shared_ptr<GeomAPI_Shape>& theSubShape)
{
const std::shared_ptr<GeomAPI_Shape>& anOldShape = value();
- bool isOldShape =
+ bool isOldContext = theContext == myRef.value();
+ bool isOldShape = isOldContext &&
(theSubShape == anOldShape || (theSubShape && anOldShape && theSubShape->isEqual(anOldShape)));
if (isOldShape) return; // shape is the same, so context is also unchanged
// update the referenced object if needed
- bool isOldContext = theContext == myRef.value();
-
-
if (!isOldContext)
myRef.setValue(theContext);
// do noth use naming if selected shape is result shape itself, but not sub-shape
TDF_Label aSelLab = selectionLabel();
aSelLab.ForgetAttribute(kSIMPLE_REF_ID);
+ aSelLab.ForgetAttribute(kCONSTUCTION_SIMPLE_REF_ID);
+
+ bool isDegeneratedEdge = false;
+ // do not use the degenerated edge as a shape, a null context and shape is used in the case
+ if (theSubShape.get() && !theSubShape->isNull() && theSubShape->isEdge()) {
+ const TopoDS_Shape& aSubShape = theSubShape->impl<TopoDS_Shape>();
+ if (aSubShape.ShapeType() == TopAbs_EDGE)
+ isDegeneratedEdge = BRep_Tool::Degenerated(TopoDS::Edge(aSubShape));
+ }
+ if (!theContext.get() || isDegeneratedEdge) {
+ // to keep the reference attribute label
+ TDF_Label aRefLab = myRef.myRef->Label();
+ aSelLab.ForgetAllAttributes(true);
+ myRef.myRef = TDF_Reference::Set(aSelLab, aSelLab);
+ return;
+ }
if (theContext->groupName() == ModelAPI_ResultBody::group()) {
// do not select the whole shape for body:it is already must be in the data framework
if (theContext->shape().get() && theContext->shape()->isEqual(theSubShape)) {
selectBody(theContext, theSubShape);
}
} else if (theContext->groupName() == ModelAPI_ResultConstruction::group()) {
- selectConstruction(theContext, theSubShape);
+ if (!theSubShape.get()) {
+ // to sub, so the whole result is selected
+ aSelLab.ForgetAllAttributes(true);
+ TDataStd_UAttribute::Set(aSelLab, kCONSTUCTION_SIMPLE_REF_ID);
+ } else {
+ selectConstruction(theContext, theSubShape);
+ }
}
myIsInitialized = true;
return aResult; // empty result
return aContext->shape();
}
+ if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, nothing is in value
+ return aResult; // empty result
+ }
Handle(TNaming_NamedShape) aSelection;
if (selectionLabel().FindAttribute(TNaming_NamedShape::GetID(), aSelection)) {
if (aSelLab.IsAttribute(kSIMPLE_REF_ID)) { // it is just reference to shape, not sub-shape
return aContext->shape() && !aContext->shape()->isNull();
}
+ if (aSelLab.IsAttribute(kCONSTUCTION_SIMPLE_REF_ID)) { // it is just reference to construction, not sub-shape
+ return aContext->shape() && !aContext->shape()->isNull();
+ }
if (aContext->groupName() == ModelAPI_ResultBody::group()) {
// body: just a named shape, use selection mechanism from OCCT
} else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) {
// construction: identification by the results indexes, recompute faces and
// take the face that more close by the indexes
- std::shared_ptr<GeomAPI_PlanarEdges> aWirePtr =
- std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext)->shape());
- if (aWirePtr && aWirePtr->hasPlane()) { // sketch sub-element
+ ResultConstructionPtr aConstructionContext =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
+ FeaturePtr aContextFeature = aContext->document()->feature(aContext);
+ // sketch sub-element
+ if (aConstructionContext &&
+ std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature).get())
+ {
TDF_Label aLab = myRef.myRef->Label();
// getting a type of selected shape
Handle(TDataStd_Integer) aTypeAttr;
bool aNoIndexes =
!aLab.FindAttribute(TDataStd_IntPackedMap::GetID(), aSubIds) || aSubIds->Extent() == 0;
// for now working only with composite features
- FeaturePtr aContextFeature = aContext->document()->feature(aContext);
CompositeFeaturePtr aComposite =
std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aContextFeature);
- if (!aComposite || aComposite->numberOfSubs() == 0) {
+ if (!aComposite.get() || aComposite->numberOfSubs() == 0) {
return false;
}
- if (aShapeType == TopAbs_FACE) {
+ if (aShapeType == TopAbs_FACE) { // compound is for the whole sketch selection
// If this is a wire with plane defined thin it is a sketch-like object
- std::list<std::shared_ptr<GeomAPI_Shape> > aFaces;
- GeomAlgoAPI_SketchBuilder::createFaces(aWirePtr->origin(), aWirePtr->dirX(),
- aWirePtr->dirY(), aWirePtr->norm(), aWirePtr, aFaces);
- if (aFaces.empty()) // no faces, update can not work correctly
+ if (!aConstructionContext->facesNum()) // no faces, update can not work correctly
return false;
// if there is no edges indexes, any face can be used: take the first
std::shared_ptr<GeomAPI_Shape> aNewSelected;
if (aNoIndexes) {
- aNewSelected = *(aFaces.begin());
+ aNewSelected = aConstructionContext->face(0);
} else { // searching for most looks-like initial face by the indexes
// prepare edges of the current resut for the fast searching
TColStd_MapOfTransient allCurves;
}
}
}
- // iterate new result faces and searching for these edges
- std::list<std::shared_ptr<GeomAPI_Shape> >::iterator aFacesIter = aFaces.begin();
double aBestFound = 0; // best percentage of found edges
- for(; aFacesIter != aFaces.end(); aFacesIter++) {
+ for(int aFaceIndex = 0; aFaceIndex < aConstructionContext->facesNum(); aFaceIndex++) {
int aFound = 0, aNotFound = 0;
- TopExp_Explorer anEdgesExp((*aFacesIter)->impl<TopoDS_Shape>(), TopAbs_EDGE);
+ TopExp_Explorer anEdgesExp(
+ aConstructionContext->face(aFaceIndex)->impl<TopoDS_Shape>(), TopAbs_EDGE);
for(; anEdgesExp.More(); anEdgesExp.Next()) {
TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
if (!anEdge.IsNull()) {
double aPercentage = double(aFound) / double(aFound + aNotFound);
if (aPercentage > aBestFound) {
aBestFound = aPercentage;
- aNewSelected = *aFacesIter;
+ aNewSelected = aConstructionContext->face(aFaceIndex);
}
}
}
std::shared_ptr<GeomAPI_Shape> aSubSh = value();
ResultPtr aCont = context();
aName = "Undefined name";
- if(!aSubSh.get() || aSubSh->isNull() || !aCont.get() || aCont->shape()->isNull())
+ if(!aCont.get() || aCont->shape()->isNull())
return aName;
+ if (!aSubSh.get() || aSubSh->isNull()) { // no subshape, so just the whole feature name
+ return aCont->data()->name();
+ }
TopoDS_Shape aSubShape = aSubSh->impl<TopoDS_Shape>();
TopoDS_Shape aContext = aCont->shape()->impl<TopoDS_Shape>();
#ifdef DEB_NAMING
+ if(aSubShape.ShapeType() == TopAbs_COMPOUND) {
BRepTools::Write(aSubShape, "Selection.brep");
BRepTools::Write(aContext, "Context.brep");
+ }
#endif
std::shared_ptr<Model_Document> aDoc =
std::dynamic_pointer_cast<Model_Document>(aCont->document());
switch (aType) {
case TopAbs_FACE:
// the Face should be in DF. If it is not the case, it is an error ==> to be debugged
- break;
- case TopAbs_EDGE:
- {
- // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case
- // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces
- TopTools_IndexedDataMapOfShapeListOfShape aMap;
- TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap);
- TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape
- bool isTrivialCase(true);
- /* for (int i = 1; i <= aMap.Extent(); i++) {
- const TopoDS_Shape& aKey = aMap.FindKey(i);
- //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key
- if (aKey.IsSame(aSubShape)) continue;
- const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i);
- // check that it is not a trivial case (F1 & F2: aNumber = 1)
- isTrivialCase = isTrivial(anAncestors, aSMap);
- break;
- }*/
- if(aMap.Contains(aSubShape)) {
- const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape);
- // check that it is not a trivial case (F1 & F2: aNumber = 1)
- isTrivialCase = isTrivial(anAncestors, aSMap);
- } else
- break;
- TopTools_ListOfShape aListOfNbs;
- if(!isTrivialCase) { // find Neighbors
- TNaming_Localizer aLocalizer;
- TopTools_MapOfShape aMap3;
- aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3);
- //int n = aMap3.Extent();
- TopTools_MapIteratorOfMapOfShape it(aMap3);
- for(;it.More();it.Next()) {
- const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge
- //TopAbs_ShapeEnum aType = aNbShape.ShapeType();
- const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape);
- TopTools_ListIteratorOfListOfShape it2(aList);
- for(;it2.More();it2.Next()) {
- if(aSMap.Contains(it2.Value())) continue; // skip this Face
- aListOfNbs.Append(it2.Value());
- }
- }
- } // else a trivial case
-
- // build name of the sub-shape Edge
- for(int i=1; i <= aSMap.Extent(); i++) {
- const TopoDS_Shape& aFace = aSMap.FindKey(i);
- std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel());
- if(i == 1)
- aName = aFaceName;
- else
- aName += "|" + aFaceName;
- }
- TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
- for (;itl.More();itl.Next()) {
- std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel());
- aName += "|" + aFaceName;
- }
- }
- break;
+ break;
+ case TopAbs_EDGE:
+ {
+ // name structure: F1 | F2 [| F3 | F4], where F1 & F2 the faces which gives the Edge in trivial case
+ // if it is not atrivial case we use localization by neighbours. F3 & F4 - neighbour faces
+ if (BRep_Tool::Degenerated(TopoDS::Edge(aSubShape))) {
+ aName = "Degenerated_Edge";
+ break;
+ }
+ TopTools_IndexedDataMapOfShapeListOfShape aMap;
+ TopExp::MapShapesAndAncestors(aContext, TopAbs_EDGE, TopAbs_FACE, aMap);
+ TopTools_IndexedMapOfShape aSMap; // map for ancestors of the sub-shape
+ bool isTrivialCase(true);
+/* for (int i = 1; i <= aMap.Extent(); i++) {
+ const TopoDS_Shape& aKey = aMap.FindKey(i);
+ //if (aKey.IsNotEqual(aSubShape)) continue; // find exactly the selected key
+ if (aKey.IsSame(aSubShape)) continue;
+ const TopTools_ListOfShape& anAncestors = aMap.FindFromIndex(i);
+ // check that it is not a trivial case (F1 & F2: aNumber = 1)
+ isTrivialCase = isTrivial(anAncestors, aSMap);
+ break;
+ }*/
+ if(aMap.Contains(aSubShape)) {
+ const TopTools_ListOfShape& anAncestors = aMap.FindFromKey(aSubShape);
+ // check that it is not a trivial case (F1 & F2: aNumber = 1)
+ isTrivialCase = isTrivial(anAncestors, aSMap);
+ } else
+ break;
+ TopTools_ListOfShape aListOfNbs;
+ if(!isTrivialCase) { // find Neighbors
+ TNaming_Localizer aLocalizer;
+ TopTools_MapOfShape aMap3;
+ aLocalizer.FindNeighbourg(aContext, aSubShape, aMap3);
+ //int n = aMap3.Extent();
+ TopTools_MapIteratorOfMapOfShape it(aMap3);
+ for(;it.More();it.Next()) {
+ const TopoDS_Shape& aNbShape = it.Key(); // neighbor edge
+ //TopAbs_ShapeEnum aType = aNbShape.ShapeType();
+ const TopTools_ListOfShape& aList = aMap.FindFromKey(aNbShape);
+ TopTools_ListIteratorOfListOfShape it2(aList);
+ for(;it2.More();it2.Next()) {
+ if(aSMap.Contains(it2.Value())) continue; // skip this Face
+ aListOfNbs.Append(it2.Value());
+ }
+ }
+ } // else a trivial case
+
+ // build name of the sub-shape Edge
+ for(int i=1; i <= aSMap.Extent(); i++) {
+ const TopoDS_Shape& aFace = aSMap.FindKey(i);
+ std::string aFaceName = GetShapeName(aDoc, aFace, selectionLabel());
+ if(i == 1)
+ aName = aFaceName;
+ else
+ aName += "|" + aFaceName;
+ }
+ TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
+ for (;itl.More();itl.Next()) {
+ std::string aFaceName = GetShapeName(aDoc, itl.Value(), selectionLabel());
+ aName += "|" + aFaceName;
+ }
+ }
+ break;
case TopAbs_VERTEX:
// name structure (Monifold Topology):
//n = aList.Extent();
#endif
int n = aList.Extent();
- if(n < 3) { // open topology case => via edges
+ if(n < 3) { // open topology case or Compound case => via edges
TopTools_IndexedDataMapOfShapeListOfShape aMap;
TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap);
- const TopTools_ListOfShape& aList2 = aMap.FindFromKey(aSubShape);
- if(aList2.Extent() >= 2) { // regular solution
- TopTools_ListIteratorOfListOfShape itl(aList2);
+ const TopTools_ListOfShape& aList22 = aMap.FindFromKey(aSubShape);
+ if(aList22.Extent() >= 2) { // regular solution
+#ifdef FIX_BUG1
+
+ // bug! duplication; fix is below
+ aFMap.Clear();
+ TopTools_ListOfShape aListE;
+ TopTools_ListIteratorOfListOfShape itl2(aList22);
+ for (int i = 1;itl2.More();itl2.Next(),i++) {
+ if(aFMap.Add(itl2.Value()))
+ aListE.Append(itl2.Value());
+ }
+ n = aListE.Extent();
+#endif
+ TopTools_ListIteratorOfListOfShape itl(aListE);
for (int i = 1;itl.More();itl.Next(),i++) {
const TopoDS_Shape& anEdge = itl.Value();
std::string anEdgeName = GetShapeName(aDoc, anEdge, selectionLabel());
else
aName += "|" + anEdgeName;
}
+ }//reg
+ else { // dangle vertex: if(aList22.Extent() == 1)
+ //it should be already in DF
}
}
else {
TopAbs_ShapeEnum translateType (const std::string& theType)
{
- TCollection_AsciiString aStr(theType.c_str());
- aStr.UpperCase();
- if(aStr.IsEqual("COMP"))
- return TopAbs_COMPOUND;
- else if(aStr.IsEqual("COMS"))
- return TopAbs_COMPSOLID;
- else if(aStr.IsEqual("SOLD"))
- return TopAbs_SOLID;
- else if(aStr.IsEqual("SHEL"))
- return TopAbs_SHELL;
- else if(aStr.IsEqual("FACE"))
- return TopAbs_FACE;
- else if(aStr.IsEqual("WIRE"))
- return TopAbs_WIRE;
- else if(aStr.IsEqual("EDGE"))
- return TopAbs_EDGE;
- else if(aStr.IsEqual("VERT"))
- return TopAbs_VERTEX;
-
+ // map from the textual shape types to OCCT enumeration
+ static std::map<std::string, TopAbs_ShapeEnum> MyShapeTypes;
+ if (MyShapeTypes.size() == 0) {
+ MyShapeTypes["face"] = TopAbs_FACE;
+ MyShapeTypes["faces"] = TopAbs_FACE;
+ MyShapeTypes["vertex"] = TopAbs_VERTEX;
+ MyShapeTypes["vertices"] = TopAbs_VERTEX;
+ MyShapeTypes["wire"] = TopAbs_WIRE;
+ MyShapeTypes["edge"] = TopAbs_EDGE;
+ MyShapeTypes["edges"] = TopAbs_EDGE;
+ MyShapeTypes["shell"] = TopAbs_SHELL;
+ MyShapeTypes["solid"] = TopAbs_SOLID;
+ MyShapeTypes["solids"] = TopAbs_SOLID;
+ MyShapeTypes["FACE"] = TopAbs_FACE;
+ MyShapeTypes["FACES"] = TopAbs_FACE;
+ MyShapeTypes["VERTEX"] = TopAbs_VERTEX;
+ MyShapeTypes["VERTICES"] = TopAbs_VERTEX;
+ MyShapeTypes["WIRE"] = TopAbs_WIRE;
+ MyShapeTypes["EDGE"] = TopAbs_EDGE;
+ MyShapeTypes["EDGES"] = TopAbs_EDGE;
+ MyShapeTypes["SHELL"] = TopAbs_SHELL;
+ MyShapeTypes["SOLID"] = TopAbs_SOLID;
+ MyShapeTypes["SOLIDS"] = TopAbs_SOLID;
+ }
+ if (MyShapeTypes.find(theType) != MyShapeTypes.end())
+ return MyShapeTypes[theType];
+ Events_Error::send("Shape type defined in XML is not implemented!");
return TopAbs_SHAPE;
}