Salome HOME
ab1d7011933b550ad6a21196800674c4c9f4b701
[modules/shaper.git] / src / ModelGeomAlgo / ModelGeomAlgo_Point2D.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        ModelAPI_Tools.cpp
4 // Created:     20 Jul 2016
5 // Author:      Natalia ERMOLAEVA
6
7 #include "ModelGeomAlgo_Point2D.h"
8
9 #include <ModelAPI_Feature.h>
10 #include <ModelAPI_Result.h>
11 #include <ModelAPI_AttributeRefAttr.h>
12 #include <ModelAPI_CompositeFeature.h>
13 #include <ModelAPI_Tools.h>
14
15 #include <ModelGeomAlgo_Shape.h>
16
17 #include <GeomAPI_ShapeIterator.h>
18
19 #include <GeomAlgoAPI_ShapeTools.h>
20 #include <GeomDataAPI_Point2D.h>
21
22 #include <GeomAPI_Pnt.h>
23 #include <GeomAPI_Pnt2d.h>
24 #include <GeomAPI_Vertex.h>
25 #include <GeomAPI_Dir.h>
26 #include <GeomAPI_Edge.h>
27 #include <GeomAPI_Lin.h>
28 #include <GeomAPI_Circ.h>
29
30 #ifdef WIN32
31 #pragma warning(disable : 4996) // for sprintf
32 #endif
33
34 namespace ModelGeomAlgo_Point2D {
35   std::shared_ptr<GeomDataAPI_Point2D> getPointOfRefAttr(ModelAPI_Feature* theFeature,
36                                                   const std::string& theAttribute,
37                                                   const std::string& theObjectFeatureKind,
38                                                   const std::string& theObjectFeatureAttribute)
39   {
40     std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
41
42     /// essential check as it is called in openGl thread
43     if (!theFeature || !theFeature->data().get() || !theFeature->data()->isValid())
44       return std::shared_ptr<GeomDataAPI_Point2D>();
45
46     FeaturePtr aFeature;
47     std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
48         ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
49     if(anAttr.get() && anAttr->isInitialized()) {
50       aFeature = ModelAPI_Feature::feature(anAttr->object());
51       if (aFeature.get()) {
52         bool aFeatureOfObjectKind = !theObjectFeatureKind.empty() &&
53                                     !theObjectFeatureAttribute.empty() &&
54                                     aFeature->getKind() == theObjectFeatureKind;
55         if(aFeatureOfObjectKind)
56             aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
57                                     aFeature->data()->attribute(theObjectFeatureAttribute));
58         else if (anAttr->attr())
59           aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
60       }
61     }
62     return aPointAttr;
63   }
64
65   void getPointsOfReference(const std::shared_ptr<ModelAPI_Object>& theObject,
66                             const std::string& theReferenceFeatureKind,
67                             std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
68                             const std::string& theObjectFeatureKind,
69                             const std::string& theObjectFeatureAttribute,
70                             const bool isSkipFeatureAttributes)
71   {
72     // find by feature
73     FeaturePtr aSourceFeature = ModelAPI_Feature::feature(theObject);
74
75     const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
76     std::set<AttributePtr>::const_iterator aIt;
77     for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
78       std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
79       FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
80       if (aRefFeature->getKind() == theReferenceFeatureKind) {
81         std::list<AttributePtr> anAttributes =
82                          aRefFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
83         std::list<AttributePtr>::iterator anIter = anAttributes.begin(), aLast = anAttributes.end();
84         bool isSkippedAttribute = false;
85         if (isSkipFeatureAttributes) {
86           for(anIter = anAttributes.begin(); anIter != aLast && !isSkippedAttribute; anIter++) {
87             AttributeRefAttrPtr aRefAttribute =
88               std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
89             if (aRefAttribute.get() && !aRefAttribute->isObject()) {
90               std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
91                              std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttribute->attr());
92               FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aPointAttr->owner());
93               isSkippedAttribute = aSourceFeature == anAttributeFeature;
94             }
95           }
96         }
97         if (isSkippedAttribute)
98           continue;
99
100         // it searches the first point of AttributeRefAtt
101         std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
102         for(anIter = anAttributes.begin(); anIter != aLast && !aPointAttr.get(); anIter++) {
103           AttributeRefAttrPtr aRefAttribute =
104             std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
105           if (aRefAttribute.get()) {
106             aPointAttr = getPointOfRefAttr(aRefFeature.get(), aRefAttribute->id(),
107                          theObjectFeatureKind, theObjectFeatureAttribute);
108           }
109         }
110         if (aPointAttr.get()) {
111           theAttributes.insert(aPointAttr);
112         }
113       }
114     }
115     // find by results
116     FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
117     if (aFeature.get()) {
118       const std::list<std::shared_ptr<ModelAPI_Result> > aResults = aFeature->results();
119       std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
120       for (; aRIter != aResults.cend(); aRIter++) {
121         ResultPtr aResult = *aRIter;
122         getPointsOfReference(aResult, theReferenceFeatureKind, theAttributes, theObjectFeatureKind,
123                              theObjectFeatureAttribute);
124       }
125     }
126   }
127
128   void appendPoint(const std::shared_ptr<GeomAPI_Pnt>& thePoint,
129                    const std::shared_ptr<ModelAPI_Result>& theResult,
130                    PointToRefsMap& thePointToAttributeOrObject)
131   {
132     if (thePointToAttributeOrObject.find(thePoint) != thePointToAttributeOrObject.end())
133       thePointToAttributeOrObject.at(thePoint).second.push_back(theResult);
134     else {
135       std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
136       std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
137       anObjects.push_back(theResult);
138       thePointToAttributeOrObject[thePoint] = std::make_pair(anAttributes, anObjects);
139     }
140   }
141
142   void appendShapePoints(const GeomShapePtr& theShape,
143                          const std::shared_ptr<ModelAPI_Result>& theResult,
144                          PointToRefsMap& thePointToAttributeOrObject)
145   {
146     if (!theShape.get())
147       return;
148
149     switch (theShape->shapeType()) {
150       case GeomAPI_Shape::VERTEX: {
151         std::shared_ptr<GeomAPI_Vertex> aVertex =
152           std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(theShape));
153         std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
154         appendPoint(aPnt, theResult, thePointToAttributeOrObject);
155       }
156       break;
157       case GeomAPI_Shape::EDGE: {
158         std::shared_ptr<GeomAPI_Edge> anEdge =
159           std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(theShape));
160         appendPoint(anEdge->firstPoint(), theResult, thePointToAttributeOrObject);
161         appendPoint(anEdge->lastPoint(), theResult, thePointToAttributeOrObject);
162       }
163       break;
164       case GeomAPI_Shape::COMPOUND: {
165         for(GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) {
166           appendShapePoints(anIt.current(), theResult, thePointToAttributeOrObject);
167         }
168       }
169       break;
170       default: break;
171     }
172   }
173
174   void getPointsIntersectedShape(const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
175                         const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
176                         PointToRefsMap& thePointToAttributeOrObject)
177   {
178     GeomShapePtr aFeatureShape;
179     {
180       std::set<ResultPtr> anEdgeShapes;
181       ModelGeomAlgo_Shape::shapesOfType(theBaseFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
182       if (anEdgeShapes.empty())
183         return;
184       aFeatureShape = (*anEdgeShapes.begin())->shape();
185     }
186
187     std::list<std::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = theFeatures.begin(),
188                                                                   aLast = theFeatures.end();
189     for (; anIt != aLast; anIt++) {
190       FeaturePtr aFeature = *anIt;
191       if (aFeature.get() == theBaseFeature.get())
192         continue;
193       if (aFeature.get()) {
194         std::set<ResultPtr> anEdgeShapes;
195         ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
196         if (anEdgeShapes.empty())
197           continue;
198         ResultPtr aResult = *anEdgeShapes.begin();
199         GeomShapePtr aShape = aResult->shape();
200
201         GeomShapePtr aShapeOfIntersection = aFeatureShape->intersect(aShape);
202         appendShapePoints(aShapeOfIntersection, aResult, thePointToAttributeOrObject);
203       }
204     }
205   }
206
207   void getPointsInsideShape(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
208                         const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
209                         const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
210                         const std::shared_ptr<GeomAPI_Dir>& theDirX,
211                         const std::shared_ptr<GeomAPI_Dir>& theDirY,
212                         PointToRefsMap& thePointToAttributeOrObject)
213   {
214     std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
215                                                             aLast = theAttributes.end();
216     for (; anIt != aLast; anIt++) {
217       std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
218       std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
219       std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
220       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
221       if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
222         if (thePointToAttributeOrObject.find(aProjectedPoint) != thePointToAttributeOrObject.end())
223           thePointToAttributeOrObject.at(aProjectedPoint).first.push_back(anAttribute);
224         else {
225           std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
226           std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
227           anAttributes.push_back(anAttribute);
228           thePointToAttributeOrObject[aProjectedPoint] = std::make_pair(anAttributes, anObjects);
229         }
230       }
231     }
232   }
233
234   void getPointsInsideShape_p(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
235                             const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
236                             const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
237                             const std::shared_ptr<GeomAPI_Dir>& theDirX,
238                             const std::shared_ptr<GeomAPI_Dir>& theDirY,
239                             std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
240                             std::map<std::shared_ptr<GeomDataAPI_Point2D>,
241                                      std::shared_ptr<GeomAPI_Pnt> >& theAttributeToPoint)
242   {
243     std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
244                                                             aLast = theAttributes.end();
245     for (; anIt != aLast; anIt++) {
246       std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
247       std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
248       std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
249       std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
250       if (isPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
251         thePoints.push_back(aProjectedPoint);
252         theAttributeToPoint[anAttribute] = aProjectedPoint;
253       }
254     }
255   }
256
257   bool isPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
258                      const std::shared_ptr<GeomAPI_Pnt>& thePoint,
259                      std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
260   {
261     bool isInside = false;
262     if (theBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
263       std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
264       if (anEdge->isLine()) {
265         std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
266         theProjectedPoint = aLine->project(thePoint);
267       }
268       else if (anEdge->isCircle() || anEdge->isArc()) {
269         std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
270         theProjectedPoint = aCircle->project(thePoint);
271       }
272       if (theProjectedPoint.get()) {
273         std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(theProjectedPoint->x(),
274                                                   theProjectedPoint->y(), theProjectedPoint->z()));
275         isInside = GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertexShape, theBaseShape);
276       }
277     }
278     return isInside;
279   }
280
281   std::string doubleToString(double theValue)
282   {
283     std::string aValueStr;
284     char aBuf[50];
285     int n = sprintf(aBuf, "%g", theValue);
286     aValueStr = std::string(aBuf);
287     return aValueStr;
288   }
289
290 #ifdef _DEBUG
291   std::string getPontAttributesInfo(const std::shared_ptr<ModelAPI_Feature>& theFeature,
292                            const std::set<std::shared_ptr<ModelAPI_Attribute> >& theAttributesOnly)
293   {
294     std::string anInfo;
295
296     std::list<AttributePtr> anAttrs = theFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
297     std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
298
299     for(; anIt != aLast; anIt++) {
300       AttributePtr anAttribute = *anIt;
301       if (anAttribute.get() && (theAttributesOnly.empty() ||
302           theAttributesOnly.find(anAttribute) != theAttributesOnly.end())) {
303       if (!anInfo.empty()) {
304         anInfo.append(", ");
305         anInfo.append("\n");
306       }
307       anInfo.append("    " + getPointAttributeInfo(anAttribute));
308       }
309     }
310     return anInfo;
311   }
312
313   std::string getPointAttributeInfo(const std::shared_ptr<ModelAPI_Attribute>& theAttribute)
314   {
315     std::string anInfo;
316     std::string aValue = "not defined";
317     std::string aType = theAttribute->attributeType();
318     if (aType == GeomDataAPI_Point2D::typeId()) {
319       std::shared_ptr<GeomDataAPI_Point2D> aPoint =
320         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
321       if (aPoint.get() && aPoint->isInitialized()) {
322         aValue = std::string("(" + doubleToString(aPoint->x()) + ", "+
323                              doubleToString(aPoint->y()) + ")");
324       }
325     }
326     anInfo.append(theAttribute->id() + ": " + aValue);
327
328     return anInfo;
329   }
330 #endif
331 } // namespace ModelGeomAlgo_Point2D