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