#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_ResultBody.h>
#include <GeomAPI_Wire.h>
+#include <GeomAPI_Edge.h>
#include <TopoDS_Iterator.hxx>
#include <TopoDS.hxx>
#include <TNaming_SameShapeIterator.hxx>
#include <TDataStd_Name.hxx>
#include <TColStd_MapOfTransient.hxx>
+#include <Precision.hxx>
#include <algorithm>
#include <stdexcept>
!aNS->Label().IsDescendant(aContextData->label())) {
isNeedContextName = false;
TDF_Label aNSDataLab = aNS->Label();
- while(aNSDataLab.Depth() != 7 && aNSDataLab.Depth() > 5)
+ if (aNSDataLab.Depth() % 2 == 0)
aNSDataLab = aNSDataLab.Father();
ObjectPtr aNewContext = theDoc->objects()->object(aNSDataLab);
- if (!aNewContext.get() && aNSDataLab.Depth() == 7) {
+ while(!aNewContext.get() && aNSDataLab.Depth() > 5) {
aNSDataLab = aNSDataLab.Father().Father();
aNewContext = theDoc->objects()->object(aNSDataLab);
}
}
} else
break;
- TopTools_ListOfShape aListOfNbs;
+ TopTools_MapOfShape aNbs;
if(!isTrivialCase) { // find Neighbors
TNaming_Localizer aLocalizer;
TopTools_MapOfShape aMap3;
TopTools_ListIteratorOfListOfShape it2(aList);
for(;it2.More();it2.Next()) {
if(aSMap.Contains(it2.Value())) continue; // skip this Face
- aListOfNbs.Append(it2.Value());
+ aNbs.Add(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);
+ // iterate faces of the context to get stable order, not map-order
+ TopTools_MapOfShape aStoredFaces; // to avoid duplicates
+ for(TopExp_Explorer aContExp(aContext, TopAbs_FACE); aContExp.More(); aContExp.Next()) {
+ const TopoDS_Shape& aFace = aContExp.Current();
+ if (aStoredFaces.Contains(aFace) || !(aSMap.Contains(aFace) || aNbs.Contains(aFace)))
+ continue;
+ aStoredFaces.Add(aFace);
std::string aFaceName = getShapeName(aDoc, aFace, theContext, theAnotherDoc, false);
- if(i == 1)
+ if(aName.empty())
aName = aFaceName;
else
aName += "&" + aFaceName;
}
- TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
- for (;itl.More();itl.Next()) {
- std::string aFaceName = getShapeName(aDoc, itl.Value(), theContext, theAnotherDoc, false);
- aName += "&" + aFaceName;
- }
}
break;
std::string getContextName(const std::string& theSubShapeName)
{
- std::string aName;
- std::string::size_type n = theSubShapeName.find('/');
- if (n == std::string::npos) return theSubShapeName;
- aName = theSubShapeName.substr(0, n);
- return aName;
+ std::string aName;
+ std::string::size_type n = theSubShapeName.find('/');
+ if (n == std::string::npos) return theSubShapeName;
+ aName = theSubShapeName.substr(0, n);
+ return aName;
}
/// Parses naming name of sketch sub-elements: takes indices and orientation
return 0; // unknown
}
+int Model_CurvesHasher::HashCode(const Handle(Geom_Curve)& theCurve, const Standard_Integer Upper)
+{
+ double aFirstParam = theCurve->FirstParameter();
+ if (aFirstParam < -1.e+100 || aFirstParam > 1.e+100)
+ aFirstParam = 0;
+ double aLastParam = theCurve->LastParameter();
+ if (aLastParam < -1.e+100 || aLastParam > 1.e+100)
+ aLastParam = 2;
+ else aLastParam = (aLastParam + aFirstParam) / 2.; // to avoid in periodic same first and last
+
+ gp_XYZ aCoordSum = theCurve->Value(aFirstParam).XYZ() + theCurve->Value(aLastParam).XYZ();
+ return ::HashCode(aCoordSum.X() + aCoordSum.Y() / 123. + aCoordSum.Z() / 123456., Upper);
+}
+bool Model_CurvesHasher::IsEqual(const Handle(Geom_Curve)& theC1, const Handle(Geom_Curve)& theC2)
+{
+ if (theC1->DynamicType() != theC2->DynamicType())
+ return false;
+ double aFirstParam1 = theC1->FirstParameter();
+ if (aFirstParam1 < -1.e+100 || aFirstParam1 > 1.e+100)
+ aFirstParam1 = 0;
+ double aFirstParam2 = theC2->FirstParameter();
+ if (aFirstParam2 < -1.e+100 || aFirstParam2 > 1.e+100)
+ aFirstParam2 = 0;
+ if (fabs(aFirstParam1 - aFirstParam2) > 1.e-9)
+ return false;
+
+ double aLastParam1 = theC1->LastParameter();
+ if (aLastParam1 < -1.e+100 || aLastParam1 > 1.e+100)
+ aLastParam1 = 2.;
+ else aLastParam1 = (aLastParam1 + aFirstParam1) / 2.; // to avoid in periodic same first and last
+ double aLastParam2 = theC2->LastParameter();
+ if (aLastParam2 < -1.e+100 || aLastParam2 > 1.e+100)
+ aLastParam2 = 2.;
+ else aLastParam2 = (aLastParam2 + aFirstParam2) / 2.; // to avoid in periodic same first and last
+
+ if (fabs(aLastParam1 - aLastParam2) > 1.e-9)
+ return false;
+
+ return theC1->Value(aFirstParam1).IsEqual(theC2->Value(aFirstParam2), Precision::Confusion()) &&
+ theC1->Value(aLastParam1).IsEqual(theC2->Value(aLastParam2), Precision::Confusion());
+}
+
+int Model_EdgesHasher::HashCode(const TopoDS_Edge& theEdge, const Standard_Integer Upper)
+{
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aFirst, aLast);
+ return Model_CurvesHasher::HashCode(aCurve, Upper);
+}
+
+bool Model_EdgesHasher::IsEqual(const TopoDS_Edge& theE1, const TopoDS_Edge& theE2)
+{
+ GeomEdgePtr aSh1(new GeomAPI_Edge);
+ aSh1->setImpl(new TopoDS_Shape(theE1));
+ GeomEdgePtr aSh2(new GeomAPI_Edge);
+ aSh2->setImpl(new TopoDS_Shape(theE2));
+ return aSh1->isEqual(aSh2);
+}
+
std::shared_ptr<GeomAPI_Shape> Model_SelectionNaming::findAppropriateFace(
std::shared_ptr<ModelAPI_Result>& theConstr,
- NCollection_DataMap<Handle(Geom_Curve), int>& theCurves, const bool theIsWire)
+ NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher>& theCurves, const bool theIsWire)
{
int aBestFound = 0; // best number of found edges (not percentage: issue 1019)
+ int aBestNotFound = 1000000; // best number of not found edges (must be minimum)
int aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation
std::shared_ptr<GeomAPI_Shape> aResult;
ResultConstructionPtr aConstructionContext =
std::list<TopoDS_Shape>::iterator aFW = aFacesWires.begin();
for(; aFW != aFacesWires.end(); aFW++) {
TopExp_Explorer anEdgesExp(*aFW, TopAbs_EDGE);
- TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curved (841)
+ TColStd_MapOfTransient alreadyProcessed; // to avoid counting edges with same curves (841)
for(; anEdgesExp.More(); anEdgesExp.Next()) {
TopoDS_Edge anEdge = TopoDS::Edge(anEdgesExp.Current());
if (!anEdge.IsNull()) {
}
}
}
+ if (theIsWire && aFound + aNotFound != 0) {
+ if (aBestNotFound > aNotFound || (aBestNotFound == aNotFound && aFound > aBestFound) ||
+ (aBestNotFound == aNotFound && aFound == aBestFound && aSameOrientation > aBestOrient)) {
+ aBestFound = aFound;
+ aBestOrient = aSameOrientation;
+ aBestNotFound = aNotFound;
+ std::shared_ptr<GeomAPI_Wire> aWire(new GeomAPI_Wire);
+ aWire->setImpl(new TopoDS_Shape(*aFW));
+ aResult = aWire;
+ }
+ aFound = 0;
+ aNotFound = 0;
+ aSameOrientation = 0;
+ }
+ }
+ if (!theIsWire) {
if (aFound + aNotFound != 0) {
- if (aFound > aBestFound ||
- (aFound == aBestFound && aSameOrientation > aBestOrient)) {
- aBestFound = aFound;
- aBestOrient = aSameOrientation;
- if (theIsWire) {
- std::shared_ptr<GeomAPI_Wire> aWire(new GeomAPI_Wire);
- aWire->setImpl(new TopoDS_Shape(*aFW));
- aResult = aWire;
- } else {
- aResult = aConstructionContext->face(aFaceIndex);
- }
+ if (aBestNotFound > aNotFound || (aBestNotFound == aNotFound && aFound > aBestFound) ||
+ (aBestNotFound == aNotFound && aFound == aBestFound && aSameOrientation > aBestOrient)) {
+ aBestFound = aFound;
+ aBestOrient = aSameOrientation;
+ aBestNotFound = aNotFound;
+ aResult = aConstructionContext->face(aFaceIndex);
}
}
}
aName.erase(std::remove(aName.begin(), aName.end(), '-'), aName.end());
aName.erase(std::remove(aName.begin(), aName.end(), '/'), aName.end());
aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end());
+ if (aName.empty())
+ return "";
// remove the last 's', 'e', 'f' and 'r' symbols:
// they are used as markers of start/end/forward/rewersed indicators
static const std::string aSyms("sefr");
aList.Append(aFace);
}
aSelection = findCommonShape(aType, aList);
+ //if (aSelection.IsNull() && aType == TopAbs_EDGE) { // try to find selection by neighbours
+ // aSelection = findCommonShapeByNB(aType, TopAbs_VERTEX, aList);
+ //}
}
}
// in case of construction, there is no registered names for all sub-elements,
return false;
// curves and orientations of edges
- NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
+ NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher> allCurves;
const int aSubNum = aComposite->numberOfSubs();
for(int a = 0; a < aSubNum; a++) {
int aSubID = aComposite->subFeatureId(a);
return false;
// curves and orientations of edges
- NCollection_DataMap<Handle(Geom_Curve), int> allCurves;
+ NCollection_DataMap<Handle(Geom_Curve), int, Model_CurvesHasher> allCurves;
const int aSubNum = aComposite->numberOfSubs();
for(int a = 0; a < aSubNum; a++) {
int aSubID = aComposite->subFeatureId(a);