Salome HOME
Make unit-tests produce an error if the function for test of naming gets feature...
[modules/shaper.git] / src / ModelGeomAlgo / ModelGeomAlgo_Point2D.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "ModelGeomAlgo_Point2D.h"
22
23 #include <ModelAPI_Feature.h>
24 #include <ModelAPI_Result.h>
25 #include <ModelAPI_AttributeRefAttr.h>
26 #include <ModelAPI_CompositeFeature.h>
27 #include <ModelAPI_Tools.h>
28
29 #include <ModelGeomAlgo_Shape.h>
30
31 #include <GeomAPI_ShapeIterator.h>
32
33 #include <GeomAlgoAPI_ShapeTools.h>
34 #include <GeomDataAPI_Point2D.h>
35
36 #include <GeomAPI_Pnt.h>
37 #include <GeomAPI_Pnt2d.h>
38 #include <GeomAPI_Vertex.h>
39 #include <GeomAPI_Dir.h>
40 #include <GeomAPI_Edge.h>
41 #include <GeomAPI_Lin.h>
42 #include <GeomAPI_Circ.h>
43 #include <GeomAPI_ShapeExplorer.h>
44
45 //#define DEBUG_POINT_INSIDE_SHAPE
46 #ifdef DEBUG_POINT_INSIDE_SHAPE
47 #include <iostream>
48 #endif
49
50 #ifdef WIN32
51 #pragma warning(disable : 4996) // for sprintf
52 #endif
53
54 std::shared_ptr<GeomDataAPI_Point2D> ModelGeomAlgo_Point2D::getPointOfRefAttr(
55                                                   ModelAPI_Feature* theFeature,
56                                                   const std::string& theAttribute,
57                                                   const std::string& theObjectFeatureKind,
58                                                   const std::string& theObjectFeatureAttribute)
59 {
60   std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
61
62   /// essential check as it is called in openGl thread
63   if (!theFeature || !theFeature->data().get() || !theFeature->data()->isValid())
64     return std::shared_ptr<GeomDataAPI_Point2D>();
65
66   FeaturePtr aFeature;
67   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr = std::dynamic_pointer_cast<
68       ModelAPI_AttributeRefAttr>(theFeature->data()->attribute(theAttribute));
69   if(anAttr.get() && anAttr->isInitialized()) {
70     aFeature = ModelAPI_Feature::feature(anAttr->object());
71     if (aFeature.get()) {
72       bool aFeatureOfObjectKind = !theObjectFeatureKind.empty() &&
73                                   !theObjectFeatureAttribute.empty() &&
74                                   aFeature->getKind() == theObjectFeatureKind;
75       if(aFeatureOfObjectKind)
76           aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
77                                   aFeature->data()->attribute(theObjectFeatureAttribute));
78       else if (anAttr->attr())
79         aPointAttr = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
80     }
81   }
82   return aPointAttr;
83 }
84
85 void ModelGeomAlgo_Point2D::getPointsOfReference(
86                             const std::shared_ptr<ModelAPI_Object>& theObject,
87                             const std::string& theReferenceFeatureKind,
88                             std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
89                             const std::string& theObjectFeatureKind,
90                             const std::string& theObjectFeatureAttribute,
91                             const bool isSkipFeatureAttributes)
92 {
93   // find by feature
94   FeaturePtr aSourceFeature = ModelAPI_Feature::feature(theObject);
95
96   const std::set<AttributePtr>& aRefsList = theObject->data()->refsToMe();
97   std::set<AttributePtr>::const_iterator aIt;
98   for (aIt = aRefsList.cbegin(); aIt != aRefsList.cend(); ++aIt) {
99     std::shared_ptr<ModelAPI_Attribute> aAttr = (*aIt);
100     FeaturePtr aRefFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aAttr->owner());
101     if (aRefFeature->getKind() == theReferenceFeatureKind) {
102       std::list<AttributePtr> anAttributes =
103                         aRefFeature->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
104       std::list<AttributePtr>::iterator anIter = anAttributes.begin(), aLast = anAttributes.end();
105       bool isSkippedAttribute = false;
106       if (isSkipFeatureAttributes) {
107         for(anIter = anAttributes.begin(); anIter != aLast && !isSkippedAttribute; anIter++) {
108           AttributeRefAttrPtr aRefAttribute =
109             std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
110           if (aRefAttribute.get() && !aRefAttribute->isObject()) {
111             std::shared_ptr<GeomDataAPI_Point2D> aPointAttr =
112                             std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aRefAttribute->attr());
113             FeaturePtr anAttributeFeature = ModelAPI_Feature::feature(aPointAttr->owner());
114             isSkippedAttribute = aSourceFeature == anAttributeFeature;
115           }
116         }
117       }
118       if (isSkippedAttribute)
119         continue;
120
121       // it searches the first point of AttributeRefAtt
122       std::shared_ptr<GeomDataAPI_Point2D> aPointAttr;
123       for(anIter = anAttributes.begin(); anIter != aLast && !aPointAttr.get(); anIter++) {
124         AttributeRefAttrPtr aRefAttribute =
125           std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
126         if (aRefAttribute.get()) {
127           aPointAttr = getPointOfRefAttr(aRefFeature.get(), aRefAttribute->id(),
128                         theObjectFeatureKind, theObjectFeatureAttribute);
129         }
130       }
131       if (aPointAttr.get()) {
132         theAttributes.insert(aPointAttr);
133       }
134     }
135   }
136   // find by results
137   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
138   if (aFeature.get()) {
139     const std::list<std::shared_ptr<ModelAPI_Result> > aResults = aFeature->results();
140     std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
141     for (; aRIter != aResults.cend(); aRIter++) {
142       ResultPtr aResult = *aRIter;
143       getPointsOfReference(aResult, theReferenceFeatureKind, theAttributes, theObjectFeatureKind,
144                             theObjectFeatureAttribute);
145     }
146   }
147 }
148
149 void appendPoint(const std::shared_ptr<GeomAPI_Pnt>& thePoint,
150                    const std::shared_ptr<ModelAPI_Result>& theResult,
151                    ModelGeomAlgo_Point2D::PointToRefsMap& thePointToAttributeOrObject)
152 {
153   bool aPointFound = false;
154   FeaturePtr aPointFeature = ModelAPI_Feature::feature(theResult);
155   // check if the given point is already in the container in attribute list
156   for (ModelGeomAlgo_Point2D::PointToRefsMap::const_iterator
157                   anIt = thePointToAttributeOrObject.begin();
158                   anIt != thePointToAttributeOrObject.end() && !aPointFound; anIt++) {
159     std::shared_ptr<GeomAPI_Pnt> aPoint = anIt->first;
160     if (aPoint->isEqual(thePoint)) {
161       std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes = anIt->second.first;
162       for (std::list<AttributePoint2DPtr>::const_iterator anAttrIt = anAttributes.begin();
163           anAttrIt != anAttributes.end() && !aPointFound; anAttrIt++) {
164         AttributePtr anAttribute = *anAttrIt;
165         aPointFound = ModelAPI_Feature::feature(anAttribute->owner()) == aPointFeature;
166       }
167     }
168   }
169
170   if (!aPointFound) {
171     if (thePointToAttributeOrObject.find(thePoint) != thePointToAttributeOrObject.end())
172       thePointToAttributeOrObject.at(thePoint).second.push_back(theResult);
173     else {
174       std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
175       std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
176       anObjects.push_back(theResult);
177       thePointToAttributeOrObject[thePoint] = std::make_pair(anAttributes, anObjects);
178     }
179 #ifdef DEBUG_POINT_INSIDE_SHAPE
180     std::cout << "["<< thePoint->x() << ", " << thePoint->y() << "," << thePoint->z() << "]";
181 #endif
182   }
183 }
184
185 void appendShapePoints(const GeomShapePtr& theShape,
186                        const std::shared_ptr<ModelAPI_Result>& theResult,
187                        ModelGeomAlgo_Point2D::PointToRefsMap& thePointToAttributeOrObject)
188 {
189   if (!theShape.get())
190     return;
191
192   switch (theShape->shapeType()) {
193     case GeomAPI_Shape::VERTEX: {
194       std::shared_ptr<GeomAPI_Vertex> aVertex =
195         std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(theShape));
196       std::shared_ptr<GeomAPI_Pnt> aPnt = aVertex->point();
197       appendPoint(aPnt, theResult, thePointToAttributeOrObject);
198     }
199     break;
200     case GeomAPI_Shape::EDGE: {
201       std::shared_ptr<GeomAPI_Edge> anEdge =
202         std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(theShape));
203       appendPoint(anEdge->firstPoint(), theResult, thePointToAttributeOrObject);
204       appendPoint(anEdge->lastPoint(), theResult, thePointToAttributeOrObject);
205     }
206     break;
207     case GeomAPI_Shape::COMPOUND: {
208       for(GeomAPI_ShapeIterator anIt(theShape); anIt.more(); anIt.next()) {
209         appendShapePoints(anIt.current(), theResult, thePointToAttributeOrObject);
210       }
211     }
212     break;
213     default: break;
214   }
215 }
216
217 void ModelGeomAlgo_Point2D::getPointsIntersectedShape(
218                         const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
219                         const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
220                         PointToRefsMap& thePointToAttributeOrObject)
221 {
222 #ifdef DEBUG_POINT_INSIDE_SHAPE
223   std::cout << "ModelGeomAlgo_Point2D::getPointsIntersectedShape" << std::endl;
224 #endif
225   GeomShapePtr aFeatureShape;
226   {
227     std::set<ResultPtr> anEdgeShapes;
228     ModelGeomAlgo_Shape::shapesOfType(theBaseFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
229     if (anEdgeShapes.empty())
230       return;
231     aFeatureShape = (*anEdgeShapes.begin())->shape();
232   }
233
234   std::list<std::shared_ptr<ModelAPI_Feature> >::const_iterator anIt = theFeatures.begin(),
235                                                                 aLast = theFeatures.end();
236   for (; anIt != aLast; anIt++) {
237     FeaturePtr aFeature = *anIt;
238     if (aFeature.get() == theBaseFeature.get())
239       continue;
240     if (aFeature.get()) {
241       std::set<ResultPtr> anEdgeShapes;
242       ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::EDGE, anEdgeShapes);
243       if (anEdgeShapes.empty())
244         ModelGeomAlgo_Shape::shapesOfType(aFeature, GeomAPI_Shape::VERTEX, anEdgeShapes);
245
246       if (anEdgeShapes.empty())
247         continue;
248       ResultPtr aResult = *anEdgeShapes.begin();
249       GeomShapePtr aShape = aResult->shape();
250
251       GeomShapePtr aShapeOfIntersection = aFeatureShape->intersect(aShape);
252 #ifdef DEBUG_POINT_INSIDE_SHAPE
253       int aPrevSize = thePointToAttributeOrObject.size();
254 #endif
255       appendShapePoints(aShapeOfIntersection, aResult, thePointToAttributeOrObject);
256 #ifdef DEBUG_POINT_INSIDE_SHAPE
257       if (aPrevSize != thePointToAttributeOrObject.size())
258         std::cout << " <- appendShapePoints"
259                   << thePointToAttributeOrObject.size() - aPrevSize << std::endl;
260 #endif
261     }
262   }
263 }
264
265 std::list<std::shared_ptr<GeomAPI_Pnt> > ModelGeomAlgo_Point2D::getSetOfPntIntersectedShape(
266                   const std::shared_ptr<ModelAPI_Feature>& theBaseFeature,
267                   const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures)
268 {
269   std::list<std::shared_ptr<GeomAPI_Pnt> > aPoints;
270
271   PointToRefsMap aRefsMap;
272   getPointsIntersectedShape(theBaseFeature, theFeatures, aRefsMap);
273
274   for (PointToRefsMap::const_iterator aPointIt = aRefsMap.begin();
275        aPointIt != aRefsMap.end(); aPointIt++)
276     aPoints.push_back(aPointIt->first);
277
278   return aPoints;
279 }
280
281 void ModelGeomAlgo_Point2D::getPointsInsideShape(
282                         const std::shared_ptr<GeomAPI_Shape> theBaseShape,
283                         const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
284                         const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
285                         const std::shared_ptr<GeomAPI_Dir>& theDirX,
286                         const std::shared_ptr<GeomAPI_Dir>& theDirY,
287                         PointToRefsMap& thePointToAttributeOrObject)
288 {
289 #ifdef DEBUG_POINT_INSIDE_SHAPE
290   std::cout << "ModelGeomAlgo_Point2D::getPointsInsideShape:" << std::endl;
291 #endif
292   std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
293                                                           aLast = theAttributes.end();
294   for (; anIt != aLast; anIt++) {
295     std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
296     std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
297     std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
298     std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
299     if (isInnerPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
300       if (thePointToAttributeOrObject.find(aProjectedPoint) != thePointToAttributeOrObject.end())
301         thePointToAttributeOrObject.at(aProjectedPoint).first.push_back(anAttribute);
302       else {
303         std::list<std::shared_ptr<GeomDataAPI_Point2D> > anAttributes;
304         std::list<std::shared_ptr<ModelAPI_Object> > anObjects;
305         anAttributes.push_back(anAttribute);
306         thePointToAttributeOrObject[aProjectedPoint] = std::make_pair(anAttributes, anObjects);
307       }
308 #ifdef DEBUG_POINT_INSIDE_SHAPE
309       std::cout << "  " << anAttribute->owner()->data()->name() << ": " << anAttribute->id()
310                 << "[" << aPoint->x() << ", " << aPoint->y() << ", " << aPoint->z() << "]"
311                 << std::endl;
312 #endif
313     }
314     else {
315 #ifdef DEBUG_POINT_INSIDE_SHAPE
316       std::cout << "  " << anAttribute->owner()->data()->name() << ": " << anAttribute->id()
317                 << "OUT of shape" << std::endl;
318 #endif
319     }
320   }
321 }
322
323 void ModelGeomAlgo_Point2D::getPointsInsideShape_p(
324                             const std::shared_ptr<GeomAPI_Shape> theBaseShape,
325                             const std::set<std::shared_ptr<GeomDataAPI_Point2D> >& theAttributes,
326                             const std::shared_ptr<GeomAPI_Pnt>& theOrigin,
327                             const std::shared_ptr<GeomAPI_Dir>& theDirX,
328                             const std::shared_ptr<GeomAPI_Dir>& theDirY,
329                             std::list<std::shared_ptr<GeomAPI_Pnt> >& thePoints,
330                             std::map<std::shared_ptr<GeomDataAPI_Point2D>,
331                                      std::shared_ptr<GeomAPI_Pnt> >& theAttributeToPoint)
332 {
333   std::set<std::shared_ptr<GeomDataAPI_Point2D> >::const_iterator anIt = theAttributes.begin(),
334                                                           aLast = theAttributes.end();
335   for (; anIt != aLast; anIt++) {
336     std::shared_ptr<GeomDataAPI_Point2D> anAttribute = *anIt;
337     std::shared_ptr<GeomAPI_Pnt2d> aPnt2d = anAttribute->pnt();
338     std::shared_ptr<GeomAPI_Pnt> aPoint = aPnt2d->to3D(theOrigin, theDirX, theDirY);
339     std::shared_ptr<GeomAPI_Pnt> aProjectedPoint;
340     if (isInnerPointOnEdge(theBaseShape, aPoint, aProjectedPoint)) {
341       thePoints.push_back(aProjectedPoint);
342       theAttributeToPoint[anAttribute] = aProjectedPoint;
343     }
344   }
345 }
346
347 bool ModelGeomAlgo_Point2D::isPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
348                      const std::shared_ptr<GeomAPI_Pnt>& thePoint,
349                      std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
350 {
351   bool isInside = false;
352   if (theBaseShape->shapeType() == GeomAPI_Shape::EDGE) {
353     std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
354     if (anEdge->isLine()) {
355       std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
356       theProjectedPoint = aLine->project(thePoint);
357     }
358     else if (anEdge->isCircle() || anEdge->isArc()) {
359       std::shared_ptr<GeomAPI_Circ> aCircle = anEdge->circle();
360       theProjectedPoint = aCircle->project(thePoint);
361     }
362     if (theProjectedPoint.get()) {
363       std::shared_ptr<GeomAPI_Vertex> aVertexShape(new GeomAPI_Vertex(theProjectedPoint->x(),
364                                                 theProjectedPoint->y(), theProjectedPoint->z()));
365       isInside = GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertexShape, theBaseShape);
366     }
367   }
368   return isInside;
369 }
370
371
372 bool ModelGeomAlgo_Point2D::isInnerPointOnEdge(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
373                      const std::shared_ptr<GeomAPI_Pnt>& thePoint,
374                      std::shared_ptr<GeomAPI_Pnt>& theProjectedPoint)
375 {
376   bool isInside = isPointOnEdge(theBaseShape, thePoint, theProjectedPoint);
377   if (isInside) {
378     std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(theBaseShape));
379     if (!anEdge->isCircle()) {
380       // check the point is not on the boundary
381       GeomVertexPtr aVertex(new GeomAPI_Vertex(theProjectedPoint->x(),
382           theProjectedPoint->y(), theProjectedPoint->z()));
383       GeomAPI_ShapeExplorer anExp(anEdge, GeomAPI_Shape::VERTEX);
384       for (; anExp.more(); anExp.next()) {
385         GeomVertexPtr aCurV = anExp.current()->vertex();
386         isInside = !GeomAlgoAPI_ShapeTools::isSubShapeInsideShape(aVertex, aCurV);
387       }
388     }
389   }
390   return isInside;
391 }
392
393 std::string doubleToString(double theValue)
394 {
395   std::string aValueStr;
396   char aBuf[50];
397   int n = sprintf(aBuf, "%g", theValue);
398   aValueStr = std::string(aBuf);
399   return aValueStr;
400 }
401
402 #ifdef _DEBUG
403 std::string ModelGeomAlgo_Point2D::getPontAttributesInfo(
404                     const std::shared_ptr<ModelAPI_Feature>& theFeature,
405                     const std::set<std::shared_ptr<ModelAPI_Attribute> >& theAttributesOnly)
406 {
407   std::string anInfo;
408
409   std::list<AttributePtr> anAttrs = theFeature->data()->attributes(
410                                                           GeomDataAPI_Point2D::typeId());
411   std::list<AttributePtr>::const_iterator anIt = anAttrs.begin(), aLast = anAttrs.end();
412
413   for(; anIt != aLast; anIt++) {
414     AttributePtr anAttribute = *anIt;
415     if (anAttribute.get() && (theAttributesOnly.empty() ||
416         theAttributesOnly.find(anAttribute) != theAttributesOnly.end())) {
417     if (!anInfo.empty()) {
418       anInfo.append(", ");
419       anInfo.append("\n");
420     }
421     anInfo.append("    " + getPointAttributeInfo(anAttribute));
422     }
423   }
424   return anInfo;
425 }
426
427 std::string ModelGeomAlgo_Point2D::getPointAttributeInfo(
428                               const std::shared_ptr<ModelAPI_Attribute>& theAttribute)
429 {
430   std::string anInfo;
431   std::string aValue = "not defined";
432   std::string aType = theAttribute->attributeType();
433   if (aType == GeomDataAPI_Point2D::typeId()) {
434     std::shared_ptr<GeomDataAPI_Point2D> aPoint =
435       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theAttribute);
436     if (aPoint.get() && aPoint->isInitialized()) {
437       aValue = std::string("(" + doubleToString(aPoint->x()) + ", "+
438                             doubleToString(aPoint->y()) + ")");
439     }
440   }
441   anInfo.append(theAttribute->id() + ": " + aValue);
442
443   return anInfo;
444 }
445 #endif