{
TopAbs_ShapeEnum aShapeType = theSubShape.ShapeType();
gp_Pnt aVertexPos;
- TColStd_MapOfTransient allCurves;
+ NCollection_Map<TopoDS_Edge> allExactEdges;
+ NCollection_Map<TopoDS_Edge, Model_EdgesHasher> allEdges;
+ NCollection_Map<Handle(Geom_Curve), Model_CurvesHasher> allCurves;
if (aShapeType == TopAbs_VERTEX) { // compare positions
aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(theSubShape));
} else {
for(TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next()) {
TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
+ allExactEdges.Add(anEdge);
+ allEdges.Add(anEdge);
Standard_Real aFirst, aLast;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
allCurves.Add(aCurve);
TColStd_PackedMapOfInteger aRefs; // indixes of sub-elements in composite
const int aSubNum = theComposite->numberOfSubs();
- for(int a = 0; a < aSubNum; a++) {
- FeaturePtr aSub = theComposite->subFeature(a);
- const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
- std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
- // there may be many shapes (circle and center): register if at least one is in selection
- for(; aRes != aResults.cend(); aRes++) {
- ResultConstructionPtr aConstr =
- std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
- if (!aConstr->shape()) {
- continue;
- }
- if (aShapeType == TopAbs_VERTEX) {
- if (aConstr->shape()->isVertex()) { // compare vertices positions
- const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
- gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
- if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
- aRefs.Add(theComposite->subFeatureId(a));
- aSubNames[theComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
- }
- } 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()));
+ // reduce equality criteria from strong to weak
+ for(int aTypeOfIdentification = 0; aTypeOfIdentification < 3; aTypeOfIdentification++) {
+ for(int a = 0; a < aSubNum; a++) {
+ FeaturePtr aSub = theComposite->subFeature(a);
+ const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aSub->results();
+ std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRes = aResults.cbegin();
+ // there may be many shapes (circle and center): register if at least one is in selection
+ for(; aRes != aResults.cend(); aRes++) {
+ ResultConstructionPtr aConstr =
+ std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aRes);
+ if (!aConstr->shape()) {
+ continue;
+ }
+ if (aShapeType == TopAbs_VERTEX) {
+ if (aConstr->shape()->isVertex()) { // compare vertices positions
+ const TopoDS_Shape& aVertex = aConstr->shape()->impl<TopoDS_Shape>();
+ gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aVertex));
if (aPnt.IsEqual(aVertexPos, Precision::Confusion())) {
- aRefs.Add(aDelta + theComposite->subFeatureId(a));
- aSubNames[aDelta + theComposite->subFeatureId(a)] =
- Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
- break;
+ aRefs.Add(theComposite->subFeatureId(a));
+ aSubNames[theComposite->subFeatureId(a)] = Model_SelectionNaming::shortName(aConstr);
+ }
+ } 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 + theComposite->subFeatureId(a));
+ aSubNames[aDelta + theComposite->subFeatureId(a)] =
+ Model_SelectionNaming::shortName(aConstr, aDelta / kSTART_VERTEX_DELTA);
+ break;
+ }
+ aDelta += kSTART_VERTEX_DELTA;
}
- aDelta += kSTART_VERTEX_DELTA;
}
- }
- } else {
- if (aConstr->shape()->isEdge()) {
- const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
- TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
- if (!anEdge.IsNull()) {
- Standard_Real aFirst, aLast;
- Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
- if (allCurves.Contains(aCurve)) {
+ } else {
+ if (aConstr->shape()->isEdge()) {
+ const TopoDS_Shape& aResShape = aConstr->shape()->impl<TopoDS_Shape>();
+ TopoDS_Edge anEdge = TopoDS::Edge(aResShape);
+ if (anEdge.IsNull())
+ continue;
+ bool aIsEqual = false;
+ if (aTypeOfIdentification == 0) { // check equality of curves
+ aIsEqual = allExactEdges.Contains(anEdge);
+ } else if (aTypeOfIdentification == 1) { // check EdgesHash equality of edges
+ aIsEqual = allEdges.Contains(anEdge);
+ } else { // check CurvesHash equality of curves
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ aIsEqual = allCurves.Contains(aCurve);
+ }
+ if (aIsEqual) {
int anID = theComposite->subFeatureId(a);
aRefs.Add(anID);
aSubNames[anID] = Model_SelectionNaming::shortName(aConstr);
// add edges to sub-label to support naming for edges selection
TopExp_Explorer anEdgeExp(theSubShape, TopAbs_EDGE);
for(; anEdgeExp.More(); anEdgeExp.Next()) {
- TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
- Standard_Real aFirst, aLast;
- Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
- if (aFaceCurve == aCurve) {
- int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, anEdge);
+ TopoDS_Edge aFaceEdge = TopoDS::Edge(anEdgeExp.Current());
+ bool aIsEqual = false;
+ if (aTypeOfIdentification == 0) { // check equality of curves
+ aIsEqual = anEdge.IsSame(aFaceEdge);
+ } else if (aTypeOfIdentification == 1) { // check EdgesHash equality of edges
+ aIsEqual = Model_EdgesHasher::IsEqual(aFaceEdge, anEdge);
+ } else { // check CurvesHash equality of curves
+ Standard_Real aFirst, aLast;
+ Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(aFaceEdge, aFirst, aLast);
+ Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
+ aIsEqual = Model_CurvesHasher::IsEqual(aFaceCurve, aCurve);
+ }
+ if (aIsEqual) {
+ int anOrient = Model_SelectionNaming::edgeOrientation(theSubShape, aFaceEdge);
anOrientations[anID] = anOrient;
}
}
}
}
}
+ if (!aRefs.IsEmpty() || aShapeType == TopAbs_VERTEX)
+ break;
}
std::stringstream aName;
// #1839 : do not store name of the feature in the tree, since this name could be changed
TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
Standard_Real aFirst, aLast;
Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
- if (aCurve == aSubCurve &&
+ if (Model_CurvesHasher::IsEqual(aCurve, aSubCurve) &&
((fabs(aFirst - aSubFirst) < 1.e-9 && fabs(aLast - aSubLast) < 1.e-9)) ||
(fabs(aFirst - aSubLast) < 1.e-9 && fabs(aLast - aSubFirst) < 1.e-9)) {
aSub = anEdge;
TopAbs_ShapeEnum aShapeType = aSubShape.ShapeType();
TDataStd_Integer::Set(aLab, (int)aShapeType);
gp_Pnt aVertexPos;
- TColStd_MapOfTransient allCurves;
+ TColStd_MapOfTransient allCurves; // curves of the sketc hsub-elements are used, so, edges are not equal
if (aShapeType == TopAbs_VERTEX) { // compare positions
aVertexPos = BRep_Tool::Pnt(TopoDS::Vertex(aSubShape));
} else {
TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExp.Current());
Standard_Real aFirst, aLast;
Handle(Geom_Curve) aFaceCurve = BRep_Tool::Curve(anEdge, aFirst, aLast);
- if (aFaceCurve == aCurve) {
+ if (Model_CurvesHasher::IsEqual(aFaceCurve, aCurve)) {
while(aUsedIDMap.Contains(anID))
anID += 100000;
aUsedIDMap.Add(anID);
} else { // searching for most looks-like initial face by the indexes
// prepare edges of the current result for the fast searching
// 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);
#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>
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 aBestOrient = 0; // for the equal "BestFound" additional parameter is orientation
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()) {
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);