#include <ModelAPI_Tools.h>
#include <GeomAPI_Shape.h>
#include <GeomAPI_PlanarEdges.h>
-#include <Events_Error.h>
+#include <Events_InfoMessage.h>
#include <TNaming_Selector.hxx>
#include <TNaming_NamedShape.hxx>
#include <TopoDS_Iterator.hxx>
#include <TNaming_Iterator.hxx>
#include <BRep_Builder.hxx>
+#include <ModelAPI_Session.h>
+
using namespace std;
//#define DEB_NAMING 1
#ifdef DEB_NAMING
aBuilder.Generated(theContext->shape()->impl<TopoDS_Shape>());
std::shared_ptr<Model_Document> aMyDoc =
std::dynamic_pointer_cast<Model_Document>(owner()->document());
- std::string aName = theContext->data()->name();
+ std::string aName = contextName(theContext);
+ // for selection in different document, add the document name
aMyDoc->addNamingName(aSelLab, aName);
TDataStd_Name::Set(aSelLab, aName.c_str());
} else { // for sketch the naming is needed in DS
//myIsInitialized = true;
owner()->data()->sendAttributeUpdated(this);
-
- std::string aSelName = namingName();
- if(!aSelName.empty())
- TDataStd_Name::Set(selectionLabel(), aSelName.c_str()); //set name
}
std::shared_ptr<GeomAPI_Shape> Model_AttributeSelection::value()
{
+ GeomShapePtr aResult;
if (myTmpContext.get() || myTmpSubShape.get()) {
- return myTmpSubShape;
+ ResultConstructionPtr aResulConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(myTmpContext);
+ if(aResulConstruction.get()) {
+ // it is just reference to construction.
+ return myTmpSubShape;
+ }
+ return myTmpSubShape.get() ? myTmpSubShape : myTmpContext->shape();
}
- std::shared_ptr<GeomAPI_Shape> aResult;
TDF_Label aSelLab = selectionLabel();
if (aSelLab.IsAttribute(kINVALID_SELECTION))
return aResult;
return myScope;
}
-/// produces theEdge orientation relatively to theContext face
-int edgeOrientation(const TopoDS_Shape& theContext, TopoDS_Edge& theEdge)
-{
- if (theContext.ShapeType() != TopAbs_FACE)
- return 0;
- TopoDS_Face aContext = TopoDS::Face(theContext);
- if (theEdge.Orientation() == TopAbs_FORWARD)
- return 1;
- if (theEdge.Orientation() == TopAbs_REVERSED)
- return -1;
- return 0; // unknown
-}
-
/// Sets the invalid flag if flag is false, or removes it if "true"
/// Returns theFlag
static bool setInvalidIfFalse(TDF_Label& theLab, const bool theFlag) {
std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape);
aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aComp));
selectConstruction(aContext, aShape);
+ } else {
+ // For correct naming selection, put the shape into the naming structure.
+ // It seems sub-shapes are not needed: only this shape is (and can be ) selected.
+ TNaming_Builder aBuilder(aSelLab);
+ aBuilder.Generated(aContext->shape()->impl<TopoDS_Shape>());
+ std::shared_ptr<Model_Document> aMyDoc =
+ std::dynamic_pointer_cast<Model_Document>(owner()->document());
+ std::string aName = contextName(aContext);
+ aMyDoc->addNamingName(aSelLab, aName);
+ TDataStd_Name::Set(aSelLab, aName.c_str());
}
return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull());
}
if (aSelLab.IsAttribute(kPART_REF_ID)) { // it is reference to the part object
std::shared_ptr<GeomAPI_Shape> aNoSelection;
- return setInvalidIfFalse(aSelLab, selectPart(aContext, aNoSelection, true));
+ bool aResult = selectPart(aContext, aNoSelection, true);
+ aResult = setInvalidIfFalse(aSelLab, aResult);
+ if (aResult) {
+ owner()->data()->sendAttributeUpdated(this);
+ }
+ return aResult;
}
if (aContext->groupName() == ModelAPI_ResultBody::group()) {
// body: just a named shape, use selection mechanism from OCCT
TNaming_Selector aSelector(aSelLab);
bool aResult = aSelector.Solve(scope()) == Standard_True;
+ aResult = setInvalidIfFalse(aSelLab, aResult); // must be before sending of updated attribute (1556)
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, aResult);
+ return aResult;
} 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
return setInvalidIfFalse(aSelLab, false);
}
- 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
+ if (aShapeType == TopAbs_FACE || aShapeType == TopAbs_WIRE) { // compound is for the whole sketch selection
+ // If this is a wire with plane defined then it is a sketch-like object
if (!aConstructionContext->facesNum()) // no faces, update can not work correctly
return setInvalidIfFalse(aSelLab, false);
// if there is no edges indexes, any face can be used: take the first
}
}
}
- int aBestFound = 0; // best number of found edges (not percentage: issue 1019)
- int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation
- for(int aFaceIndex = 0; aFaceIndex < aConstructionContext->facesNum(); aFaceIndex++) {
- int aFound = 0, aNotFound = 0, aSameOrientation = 0;
- TopoDS_Face aFace =
- TopoDS::Face(aConstructionContext->face(aFaceIndex)->impl<TopoDS_Shape>());
- TopExp_Explorer anEdgesExp(aFace, TopAbs_EDGE);
- TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841)
- for(; anEdgesExp.More(); anEdgesExp.Next()) {
- TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
- if (!anEdge.IsNull()) {
- Standard_Real aFirst, aLast;
- Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
- if (alreadyProcessed.Contains(aCurve))
- continue;
- alreadyProcessed.Add(aCurve);
- if (allCurves.IsBound(aCurve)) {
- aFound++;
- int anOrient = allCurves.Find(aCurve);
- if (anOrient != 0) { // extra comparision score is orientation
- if (edgeOrientation(aFace, anEdge) == anOrient)
- aSameOrientation++;
- }
- } else {
- aNotFound++;
- }
- }
- }
- if (aFound + aNotFound != 0) {
- if (aFound > aBestFound ||
- (aFound == aBestFound && aSameOrientation > aBestOrient)) {
- aBestFound = aFound;
- aBestOrient = aSameOrientation;
- aNewSelected = aConstructionContext->face(aFaceIndex);
- }
- }
- }
+ aNewSelected = Model_SelectionNaming::findAppropriateFace(aContext, allCurves);
}
if (aNewSelected) { // store this new selection
+ if (aShapeType == TopAbs_WIRE) { // just get a wire from face to have wire
+ TopExp_Explorer aWireExp(aNewSelected->impl<TopoDS_Shape>(), TopAbs_WIRE);
+ if (aWireExp.More()) {
+ aNewSelected.reset(new GeomAPI_Shape);
+ aNewSelected->setImpl<TopoDS_Shape>(new TopoDS_Shape(aWireExp.Current()));
+ }
+ }
selectConstruction(aContext, aNewSelected);
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
} else { // if the selection is not found, put the empty shape: it's better to have disappeared shape, than the old, the lost one
TNaming_Builder anEmptyBuilder(selectionLabel());
return setInvalidIfFalse(aSelLab, false);
std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIter);
if (aRes && aRes->shape() && aRes->shape()->isEdge()) { // found!
selectConstruction(aContext, aRes->shape());
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
}
}
}
if (aRes && aRes->shape()) {
if (aRes->shape()->isVertex() && aVertexNum == 0) { // found!
selectConstruction(aContext, aRes->shape());
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
} else if (aRes->shape()->isEdge() && aVertexNum > 0) {
const TopoDS_Shape& anEdge = aRes->shape()->impl<TopoDS_Shape>();
int aVIndex = 1;
std::shared_ptr<GeomAPI_Shape> aVertex(new GeomAPI_Shape);
aVertex->setImpl(new TopoDS_Shape(aVExp.Current()));
selectConstruction(aContext, aVertex);
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
}
aVIndex++;
}
}
} else { // simple construction element: the selected is that needed
selectConstruction(aContext, aContext->shape());
+ setInvalidIfFalse(aSelLab, true);
owner()->data()->sendAttributeUpdated(this);
- return setInvalidIfFalse(aSelLab, true);
+ return true;
}
}
return setInvalidIfFalse(aSelLab, false); // unknown case
if (aResult) {
aContext = aResult->shape()->impl<TopoDS_Shape>();
} else {
- Events_Error::send("A result with shape is expected");
+ Events_InfoMessage("Model_AttributeSelection", "A result with shape is expected").send();
return;
}
}
static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape,
const int theID, const FeaturePtr& theContextFeature, std::shared_ptr<Model_Document> theDoc,
std::string theAdditionalName, std::map<int, int>& theOrientations,
+ std::map<int, std::string>& theSubNames, // name of sub-elements by ID to be exported instead of indexes
Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(),
const int theOrientation = 0)
{
TNaming_Builder aBuilder(aLab);
aBuilder.Generated(theShape);
std::stringstream aName;
- aName<<theContextFeature->name()<<"/";
- if (!theAdditionalName.empty())
- aName<<theAdditionalName<<"/";
- if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face";
- else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
- else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex";
-
- if (theRefs.IsNull()) {
- aName<<theID;
- if (theOrientation == 1)
- aName<<"f";
- else if (theOrientation == -1)
- aName<<"r";
- } else { // make a composite name from all sub-elements indexes: "1_2_3_4"
- TColStd_MapIteratorOfPackedMapOfInteger aRef(theRefs->GetMap());
- for(; aRef.More(); aRef.Next()) {
- aName<<"-"<<aRef.Key();
- if (theOrientations.find(aRef.Key()) != theOrientations.end()) {
- if (theOrientations[aRef.Key()] == 1)
- aName<<"f";
- else if (theOrientations[aRef.Key()] == -1)
- aName<<"r";
+ // add the part name if the selected object is located in other part
+ if (theDoc != theContextFeature->document()) {
+ if (theContextFeature->document() == ModelAPI_Session::get()->moduleDocument()) {
+ aName<<theContextFeature->document()->kind()<<"/";
+ } else {
+ ResultPtr aDocRes = ModelAPI_Tools::findPartResult(
+ ModelAPI_Session::get()->moduleDocument(), theContextFeature->document());
+ if (aDocRes.get()) {
+ aName<<aDocRes->data()->name()<<"/";
+ }
+ }
+ }
+ aName<<theContextFeature->name();
+ if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction
+ aName<<"/";
+ if (!theAdditionalName.empty())
+ aName<<theAdditionalName<<"/";
+ if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face";
+ else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire";
+ else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
+ else if (theShape.ShapeType() == TopAbs_VERTEX) aName<<"Vertex";
+
+ if (theRefs.IsNull()) {
+ aName<<theID;
+ if (theOrientation == 1)
+ aName<<"f";
+ else if (theOrientation == -1)
+ aName<<"r";
+ } else { // make a composite name from all sub-elements indexes: "1_2_3_4"
+ TColStd_MapIteratorOfPackedMapOfInteger aRef(theRefs->GetMap());
+ for(; aRef.More(); aRef.Next()) {
+ aName<<"-"<<theSubNames[aRef.Key()];
+ if (theOrientations.find(aRef.Key()) != theOrientations.end()) {
+ if (theOrientations[aRef.Key()] == 1)
+ aName<<"f";
+ else if (theOrientations[aRef.Key()] == -1)
+ aName<<"r";
+ }
}
}
}
// saving of context is enough: result construction contains exactly the needed shape
TNaming_Builder aBuilder(selectionLabel());
aBuilder.Generated(aSubShape);
- aMyDoc->addNamingName(selectionLabel(), theContext->data()->name());
- TDataStd_Name::Set(selectionLabel(), theContext->data()->name().c_str());
+ std::string aName = contextName(theContext);
+ aMyDoc->addNamingName(selectionLabel(), aName);
+ TDataStd_Name::Set(selectionLabel(), aName.c_str());
return;
}
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(owner()->data());
// iterate and store the result ids of sub-elements and sub-elements to sub-labels
Handle(TDataStd_IntPackedMap) aRefs = TDataStd_IntPackedMap::Set(aLab);
std::map<int, int> anOrientations; //map from edges IDs to orientations of these edges in face
+ std::map<int, std::string> aSubNames; //map from edges IDs to names of edges
aRefs->Clear();
const int aSubNum = aComposite->numberOfSubs();
for(int a = 0; a < aSubNum; a++) {
gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
aRefs->Add(aComposite->subFeatureId(a));
+ aSubNames[aComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
}
- } else { // get first or last vertex of the edge: last is stored with negative sign
+ } else { // get first or last vertex of the edge: last is stored with additional delta
const TopoDS_Shape& anEdge = aConstr->shape()->impl<TopoDS_Shape>();
int aDelta = kSTART_VERTEX_DELTA;
for(TopExp_Explorer aVExp(anEdge, TopAbs_VERTEX); aVExp.More(); aVExp.Next()) {
gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVExp.Current()));
if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
aRefs->Add(aDelta + aComposite->subFeatureId(a));
+ aSubNames[aDelta + aComposite->subFeatureId(a)] =
+ Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
break;
}
aDelta += kSTART_VERTEX_DELTA;
if (allCurves.Contains(aCurve)) {
int anID = aComposite->subFeatureId(a);
aRefs->Add(anID);
+ aSubNames[anID] = Model_SelectionNaming::shortName(aConstr);
if (aShapeType != TopAbs_EDGE) { // face needs the sub-edges on sub-labels
// add edges to sub-label to support naming for edges selection
TopExp_Explorer anEdgeExp(aSubShape, TopAbs_EDGE);
Standard_Real aFirst, aLast;
Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
if (aFaceCurve == aCurve) {
- int anOrient = edgeOrientation(aSubShape, anEdge);
+ int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge);
anOrientations[anID] = anOrient;
registerSubShape(
selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, "", anOrientations,
- Handle(TDataStd_IntPackedMap)(), anOrient);
+ aSubNames, Handle(TDataStd_IntPackedMap)(), anOrient);
}
}
} else { // put vertices of the selected edge to sub-labels
std::stringstream anAdditionalName;
registerSubShape(
- selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations);
+ selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations,
+ aSubNames);
}
}
}
TNaming_Builder aBuilder(selectionLabel());
aBuilder.Generated(aSubShape);
registerSubShape(
- selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aRefs);
+ selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aSubNames, aRefs);
}
bool Model_AttributeSelection::selectPart(
std::string aName("");
if(!this->isInitialized())
return !theDefaultName.empty() ? theDefaultName : aName;
- Handle(TDataStd_Name) anAtt;
- if(selectionLabel().FindAttribute(TDataStd_Name::GetID(), anAtt)) {
- aName = TCollection_AsciiString(anAtt->Get()).ToCString();
- return aName;
- }
std::shared_ptr<GeomAPI_Shape> aSubSh = value();
ResultPtr aCont = context();
}
return anID;
}
+
+void Model_AttributeSelection::setId(int theID)
+{
+ const ResultPtr& aContext = context();
+ std::shared_ptr<GeomAPI_Shape> aSelection;
+
+ std::shared_ptr<GeomAPI_Shape> aContextShape = aContext->shape();
+ // support for compsolids:
+ if (aContext.get() && ModelAPI_Tools::compSolidOwner(aContext).get())
+ aContextShape = ModelAPI_Tools::compSolidOwner(aContext)->shape();
+
+ TopoDS_Shape aMainShape = aContextShape->impl<TopoDS_Shape>();
+ // searching for the latest main shape
+ if (theID > 0 &&
+ aContextShape && !aContextShape->isNull())
+ {
+ std::shared_ptr<Model_Document> aDoc =
+ std::dynamic_pointer_cast<Model_Document>(aContext->document());
+ if (aDoc.get()) {
+ Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aMainShape, aDoc->generalLabel());
+ if (!aNS.IsNull()) {
+ aMainShape = TNaming_Tool::CurrentShape(aNS);
+ }
+ }
+
+ TopTools_IndexedMapOfShape aSubShapesMap;
+ TopExp::MapShapes(aMainShape, aSubShapesMap);
+ const TopoDS_Shape& aSelShape = aSubShapesMap.FindKey(theID);
+
+ std::shared_ptr<GeomAPI_Shape> aResult(new GeomAPI_Shape);
+ aResult->setImpl(new TopoDS_Shape(aSelShape));
+
+ aSelection = aResult;
+ }
+
+ setValue(aContext, aSelection);
+}
+
+std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) const
+{
+ std::string aResult;
+ if (owner()->document() != theContext->document()) {
+ if (theContext->document() == ModelAPI_Session::get()->moduleDocument()) {
+ aResult = theContext->document()->kind() + "/";
+ } else {
+ ResultPtr aDocRes = ModelAPI_Tools::findPartResult(
+ ModelAPI_Session::get()->moduleDocument(), theContext->document());
+ if (aDocRes.get()) {
+ aResult = aDocRes->data()->name() + "/";
+ }
+ }
+ }
+ aResult += theContext->data()->name();
+ return aResult;
+}