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