Salome HOME
569f3fd9e375c4eb3c46d9d96750e81093146b3d
[modules/shaper.git] / src / FiltersPlugin / FiltersPlugin_FeatureEdges.cpp
1 // Copyright (C) 2014-2023  CEA, EDF
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "FiltersPlugin_FeatureEdges.h"
21
22 #include <ModelAPI_AttributeString.h>
23 #include <ModelAPI_AttributeDouble.h>
24 #include <ModelAPI_ResultBody.h>
25 #include <ModelAPI_Tools.h>
26
27 #include <GeomAPI_Edge.h>
28 #include <GeomAPI_Shape.h>
29 #include <GeomAPI_ShapeExplorer.h>
30 #include <GeomAPI_Wire.h>
31
32 #include <GeomAlgoAPI_ShapeTools.h>
33
34 #include <Precision.hxx>
35
36 #include <map>
37 #include <math.h>
38 #include <iostream>
39
40 typedef std::map<GeomShapePtr, SetOfShapes, GeomAPI_Shape::Comparator> MapShapeAndAncestors;
41
42 //=================================================================================================
43 static void mapEdgesAndFaces(const GeomShapePtr theShape, MapShapeAndAncestors& theMap)
44 {
45   GeomAPI_ShapeExplorer aFExp(theShape, GeomAPI_Shape::FACE);
46   for (; aFExp.more(); aFExp.next()) {
47     GeomShapePtr aFace = aFExp.current();
48     GeomAPI_ShapeExplorer aEExp(aFace, GeomAPI_Shape::EDGE);
49     for (; aEExp.more(); aEExp.next())
50       theMap[aEExp.current()].insert(aFace);
51   }
52 }
53
54 //=================================================================================================
55 static void cacheFeatureEdge(const GeomShapePtr theTopLevelShape,
56                              SetOfShapes& theCache,
57                              const double & theAngle)
58 {
59   if (!theTopLevelShape)
60     return;
61
62   MapShapeAndAncestors anEdgesToFaces;
63   mapEdgesAndFaces(theTopLevelShape, anEdgesToFaces);
64
65   MapShapeAndAncestors::const_iterator aIt;
66   for (aIt = anEdgesToFaces.begin(); aIt != anEdgesToFaces.end(); ++aIt) {
67     GeomEdgePtr anEdge;
68     anEdge = GeomEdgePtr(new GeomAPI_Edge(aIt->first));
69
70     for (SetOfShapes::const_iterator aFIt = aIt->second.begin();
71          aFIt != aIt->second.end(); ++aFIt) {
72       SetOfShapes::const_iterator aFIt2 = aFIt;
73       ++aFIt2;
74       for (;aFIt2 != aIt->second.end(); ++aFIt2) {
75         std::string anError;
76         if (theCache.find(*aFIt) == theCache.end()) {
77           if (theAngle < Precision::Confusion()
78               || !GeomAlgoAPI_ShapeTools::isContinuousFaces(*aFIt,
79                                                          *aFIt2,
80                                                          anEdge->middlePoint(),
81                                                          theAngle,
82                                                          anError)) {
83             if (anError.empty())
84               theCache.insert(anEdge);
85           }
86         }
87       }
88     }
89   }
90 }
91
92 //=================================================================================================
93 bool FiltersPlugin_FeatureEdges::isSupported(GeomAPI_Shape::ShapeType theType) const
94 {
95   return theType == GeomAPI_Shape::EDGE;
96 }
97
98 //=================================================================================================
99 bool FiltersPlugin_FeatureEdges::isOk(const GeomShapePtr& theShape, const ResultPtr& theResult,
100                                       const ModelAPI_FiltersArgs& theArgs) const
101 {
102   AttributePtr anAttr = theArgs.argument("value");
103   AttributeDoublePtr aValue = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttr);
104
105   if (!aValue.get() || !anAttr->isInitialized())
106     return false;
107   double anAngle = aValue->value();
108
109   // check base result
110   ResultBodyPtr aBaseResult = ModelAPI_Tools::bodyOwner(theResult, true);
111   if (!aBaseResult) {
112     aBaseResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
113     if (!aBaseResult.get()) {
114       return false;
115     }
116   }
117   if (fabs(myAngle - anAngle) > 1e-10
118       || !myBaseShape
119       || !myBaseShape->isSame(aBaseResult->shape())) {
120     const_cast<FiltersPlugin_FeatureEdges*>(this)->myAngle = anAngle;
121     const_cast<FiltersPlugin_FeatureEdges*>(this)->myBaseShape = aBaseResult->shape();
122     const_cast<FiltersPlugin_FeatureEdges*>(this)->myCachedShapes.clear();
123   }
124
125   if (myCachedShapes.empty()) {
126
127     cacheFeatureEdge(aBaseResult->shape(),
128                      const_cast<FiltersPlugin_FeatureEdges*>(this)->myCachedShapes, anAngle);
129   }
130
131   return myCachedShapes.find(theShape) != myCachedShapes.end();
132 }
133
134 //=================================================================================================
135 std::string FiltersPlugin_FeatureEdges::xmlRepresentation() const
136 {
137   return xmlFromFile("filter-FeatureEdges.xml");
138 }
139
140 //=================================================================================================
141 void FiltersPlugin_FeatureEdges::initAttributes(ModelAPI_FiltersArgs& theArguments)
142 {
143   theArguments.initAttribute("value", ModelAPI_AttributeDouble::typeId());
144 }